Spaces:
Sleeping
Sleeping
| """Test patterns and best practices examples. | |
| This module demonstrates various testing patterns and best practices | |
| used throughout the test suite. | |
| """ | |
| import pytest | |
| from unittest.mock import Mock, patch, MagicMock, call | |
| from factory import Factory, Faker, SubFactory | |
| import json | |
| from pathlib import Path | |
| class TestPatterns: | |
| """Examples of different testing patterns.""" | |
| def test_basic_unit_test(self): | |
| """Basic unit test pattern.""" | |
| # Arrange | |
| input_value = 10 | |
| expected_result = 20 | |
| # Act | |
| result = input_value * 2 | |
| # Assert | |
| assert result == expected_result | |
| def test_with_fixture(self, sample_market_data): | |
| """Test using fixture data.""" | |
| # Arrange & Act | |
| symbol = sample_market_data['symbol'] | |
| price = sample_market_data['price'] | |
| # Assert | |
| assert symbol == 'AAPL' | |
| assert price == 150.0 | |
| def test_with_mock(self, mock_market_processor): | |
| """Test using mock objects.""" | |
| # Arrange | |
| test_data = {'price': 100} | |
| # Act | |
| result = mock_market_processor.process_data(test_data) | |
| # Assert | |
| assert result == {'processed': True} | |
| mock_market_processor.process_data.assert_called_once_with(test_data) | |
| def test_with_patch_decorator(self, mock_processor_class): | |
| """Test using patch decorator.""" | |
| # Arrange | |
| mock_instance = Mock() | |
| mock_instance.analyze_trends.return_value = {'trend': 'bullish'} | |
| mock_processor_class.return_value = mock_instance | |
| # Act | |
| from src.core.advanced_market_processing import AdvancedMarketProcessor | |
| processor = AdvancedMarketProcessor() | |
| result = processor.analyze_trends() | |
| # Assert | |
| assert result == {'trend': 'bullish'} | |
| mock_processor_class.assert_called_once() | |
| def test_with_context_manager_patch(self): | |
| """Test using patch as context manager.""" | |
| with patch('builtins.open', create=True) as mock_open: | |
| mock_open.return_value.__enter__.return_value.read.return_value = 'test data' | |
| # Act | |
| with open('test_file.txt', 'r') as f: | |
| content = f.read() | |
| # Assert | |
| assert content == 'test data' | |
| mock_open.assert_called_once_with('test_file.txt', 'r') | |
| def test_exception_handling(self): | |
| """Test exception handling patterns.""" | |
| # Test that exception is raised | |
| with pytest.raises(ValueError, match="Invalid input"): | |
| raise ValueError("Invalid input") | |
| # Test that no exception is raised | |
| try: | |
| result = 1 + 1 | |
| assert result == 2 | |
| except Exception as e: | |
| pytest.fail(f"Unexpected exception: {e}") | |
| def test_parametrized(self, input_value, expected): | |
| """Parametrized test pattern.""" | |
| result = input_value * 2 | |
| assert result == expected | |
| def test_slow_operation(self): | |
| """Test marked as slow.""" | |
| import time | |
| time.sleep(0.1) # Simulate slow operation | |
| assert True | |
| def test_with_caplog(self, caplog): | |
| """Test log capture pattern.""" | |
| import logging | |
| logger = logging.getLogger('test_logger') | |
| logger.info('Test log message') | |
| assert 'Test log message' in caplog.text | |
| assert caplog.records[0].levelname == 'INFO' | |
| def test_with_temp_file(self, tmp_path): | |
| """Test with temporary file.""" | |
| # Create temporary file | |
| test_file = tmp_path / "test.txt" | |
| test_file.write_text("test content") | |
| # Test | |
| content = test_file.read_text() | |
| assert content == "test content" | |
| assert test_file.exists() | |
| def test_async_function(self): | |
| """Test async function pattern.""" | |
| import asyncio | |
| async def async_function(): | |
| await asyncio.sleep(0.01) | |
| return "async result" | |
| # Run async test | |
| result = asyncio.run(async_function()) | |
| assert result == "async result" | |
| def test_mock_multiple_calls(self): | |
| """Test mock with multiple calls.""" | |
| mock_func = Mock() | |
| mock_func.side_effect = [1, 2, 3] | |
| # Multiple calls | |
| assert mock_func() == 1 | |
| assert mock_func() == 2 | |
| assert mock_func() == 3 | |
| # Verify call count | |
| assert mock_func.call_count == 3 | |
| # Verify call arguments | |
| expected_calls = [call(), call(), call()] | |
| mock_func.assert_has_calls(expected_calls) | |
| def test_mock_side_effect_exception(self): | |
| """Test mock raising exception.""" | |
| mock_func = Mock() | |
| mock_func.side_effect = ValueError("Mock error") | |
| with pytest.raises(ValueError, match="Mock error"): | |
| mock_func() | |
| def test_json_data_loading(self, test_data_dir): | |
| """Test loading JSON test data.""" | |
| json_file = test_data_dir / "sample_market_data.json" | |
| if json_file.exists(): | |
| with open(json_file) as f: | |
| data = json.load(f) | |
| assert 'market_data' in data | |
| assert len(data['market_data']) > 0 | |
| else: | |
| pytest.skip("Test data file not found") | |
| class TestFactoryPatterns: | |
| """Examples using Factory Boy for test data generation.""" | |
| class MarketDataFactory(Factory): | |
| """Factory for generating market data.""" | |
| class Meta: | |
| model = dict | |
| symbol = Faker('random_element', elements=['AAPL', 'GOOGL', 'MSFT', 'AMZN']) | |
| price = Faker('pyfloat', left_digits=3, right_digits=2, positive=True) | |
| volume = Faker('pyint', min_value=100000, max_value=10000000) | |
| timestamp = Faker('date_time_this_year') | |
| def test_with_factory(self): | |
| """Test using factory-generated data.""" | |
| market_data = self.MarketDataFactory() | |
| assert 'symbol' in market_data | |
| assert 'price' in market_data | |
| assert 'volume' in market_data | |
| assert market_data['price'] > 0 | |
| assert market_data['volume'] > 0 | |
| def test_factory_batch(self): | |
| """Test generating batch data with factory.""" | |
| batch_data = self.MarketDataFactory.build_batch(5) | |
| assert len(batch_data) == 5 | |
| for item in batch_data: | |
| assert 'symbol' in item | |
| assert 'price' in item | |
| class TestIntegrationPatterns: | |
| """Integration test patterns.""" | |
| def test_database_integration(self, database_connection): | |
| """Integration test with database.""" | |
| cursor = database_connection.cursor() | |
| # Insert test data | |
| cursor.execute( | |
| "INSERT INTO logs (timestamp, level, message) VALUES (?, ?, ?)", | |
| ('2024-01-01 10:00:00', 'INFO', 'Test message') | |
| ) | |
| database_connection.commit() | |
| # Query data | |
| cursor.execute("SELECT * FROM logs WHERE message = ?", ('Test message',)) | |
| result = cursor.fetchone() | |
| assert result is not None | |
| assert result['level'] == 'INFO' | |
| def test_api_integration(self, mock_external_apis): | |
| """Integration test with external APIs.""" | |
| mock_yf, mock_requests = mock_external_apis | |
| # Test would use actual API calls here | |
| # but they're mocked for testing | |
| import yfinance as yf | |
| data = yf.download('AAPL') | |
| assert not data.empty | |
| mock_yf.assert_called_once_with('AAPL') | |
| class TestPerformancePatterns: | |
| """Performance testing patterns.""" | |
| def test_performance_benchmark(self, benchmark): | |
| """Performance test using pytest-benchmark.""" | |
| def function_to_test(): | |
| return sum(range(1000)) | |
| result = benchmark(function_to_test) | |
| assert result == 499500 | |
| def test_memory_usage(self): | |
| """Test memory usage patterns.""" | |
| import psutil | |
| import os | |
| process = psutil.Process(os.getpid()) | |
| initial_memory = process.memory_info().rss | |
| # Perform memory-intensive operation | |
| large_list = [i for i in range(100000)] | |
| final_memory = process.memory_info().rss | |
| memory_increase = final_memory - initial_memory | |
| # Assert memory increase is reasonable | |
| assert memory_increase > 0 | |
| assert len(large_list) == 100000 | |
| class TestSecurityPatterns: | |
| """Security testing patterns.""" | |
| def test_input_validation(self): | |
| """Test input validation patterns.""" | |
| # Test SQL injection prevention | |
| malicious_input = "'; DROP TABLE users; --" | |
| # Your validation function should handle this | |
| # This is just an example pattern | |
| def validate_input(user_input): | |
| if any(char in user_input for char in [';', '--', 'DROP', 'DELETE']): | |
| raise ValueError("Invalid input detected") | |
| return user_input | |
| with pytest.raises(ValueError, match="Invalid input detected"): | |
| validate_input(malicious_input) | |
| def test_sensitive_data_handling(self): | |
| """Test sensitive data handling.""" | |
| # Test that sensitive data is not logged | |
| sensitive_data = "password123" | |
| # Mock logger to verify sensitive data is not logged | |
| with patch('logging.getLogger') as mock_logger: | |
| mock_log_instance = Mock() | |
| mock_logger.return_value = mock_log_instance | |
| # Function that should not log sensitive data | |
| def process_login(password): | |
| logger = mock_logger() | |
| logger.info("Login attempt") | |
| # Should NOT log the password | |
| return len(password) > 0 | |
| result = process_login(sensitive_data) | |
| assert result is True | |
| # Verify password was not logged | |
| logged_calls = mock_log_instance.info.call_args_list | |
| for call_args in logged_calls: | |
| assert sensitive_data not in str(call_args) |