Fixtures provide reusable test setup/teardown, defined using @pytest.fixture decorator. Support dependency injection, different scopes (function, class, module, session). Enable clean test organization, resource sharing. Example: database connections, test data setup.
Use coverage.py or pytest-cov. Run tests with coverage collection, generate reports. Analyze uncovered lines, branches. Set minimum coverage requirements. Consider meaningful vs. superficial coverage. Focus on critical paths.
Markers (@pytest.mark) categorize tests, control execution. Built-in markers: skip, skipif, xfail. Custom markers for test organization, selection. Register markers in pytest.ini. Consider marker documentation, organization.
Test doubles replace real dependencies. Mocks verify interactions, stubs provide canned responses, fakes implement lightweight alternatives. Choose based on test needs. Consider interaction vs. state testing.
Group related tests, use clear naming conventions. Separate unit/integration tests. Follow AAA pattern (Arrange-Act-Assert). Maintain test independence. Consider test discoverability, maintenance.
Plugins extend pytest functionality. Common plugins: pytest-cov, pytest-mock, pytest-django. Install via pip, configure in pytest.ini. Consider plugin interactions, maintenance. Document plugin requirements.
Use pytest-xdist for parallel testing. Consider test isolation, shared resources. Handle race conditions. Implement proper cleanup. Balance parallelism vs. resource usage.
Test input validation, authentication, authorization. Use security testing tools (bandit). Consider vulnerability scanning. Test security configurations. Document security requirements.
Integrate tests in CI/CD pipeline. Automate test execution, reporting. Consider test selection, prioritization. Handle test failures appropriately. Document test requirements.
unittest is built-in, class-based, requires test classes inheriting from TestCase. pytest is more flexible, supports function-based tests, better fixtures, parametrization, and plugins. pytest has more powerful assertions and better error reporting. Consider project needs for framework choice.
Mocking replaces real objects with test doubles. Use unittest.mock or pytest-mock. MagicMock/Mock classes provide automatic attribute creation. Common uses: external services, databases, file operations. Consider patch decorator/context manager.
Use hypothesis library for property-based testing. Define properties, let framework generate test cases. Useful for finding edge cases. Consider strategy definition, test case generation. Handle test case reduction.
conftest.py provides shared fixtures across multiple test files. Defines test configuration, custom markers. Supports fixture overriding, plugin hooks. Consider scope organization, reusability.
Use pytest-benchmark for performance tests. Measure execution time, resource usage. Consider baseline comparisons, statistical analysis. Handle environment variations. Document performance requirements.
Monkey patching modifies objects/modules at runtime for testing. Use pytest.monkeypatch fixture. Handle cleanup properly. Consider implications on test isolation. Use sparingly, prefer dependency injection.
Use pytest.raises context manager or unittest.assertRaises. Test exception types, messages. Consider exception inheritance, multiple exceptions. Test cleanup handling. Verify exception context.
Use requests, pytest-httpx for HTTP testing. Mock external services appropriately. Consider response validation, error cases. Handle authentication, rate limiting. Test different HTTP methods.
Use environment variables, configuration files. Implement test environment management. Consider CI/CD integration. Handle sensitive data properly. Document environment requirements.
Scopes: function (default), class, module, session. Choose based on resource costs, test isolation needs. Consider cleanup timing. Handle dependencies between fixtures. Document scope requirements.
Use PyTest-Qt, PyAutoGUI for GUI testing. Handle event loops properly. Consider screenshot comparisons. Test user interactions. Handle window management. Document visual requirements.
Use test databases, fixtures for setup/teardown. Consider transaction rollback, database isolation. Mock database when appropriate. Implement proper cleanup. Use tools like pytest-django for framework-specific support.
Use pytest-bdd or behave for BDD. Write tests in Gherkin syntax. Map steps to test code. Consider stakeholder communication. Balance readability vs. maintenance. Document behavior specifications.
Avoid test interdependence, slow tests, excessive mocking. Don't test implementation details. Avoid non-deterministic tests. Consider maintenance cost. Document test assumptions clearly.
Use @pytest.mark.parametrize decorator to run same test with different inputs. Supports multiple parameters, custom IDs. Reduces test code duplication. Example: @pytest.mark.parametrize('input,expected', [(1,2), (2,4)]). Consider data organization.
Use pytest-asyncio for async tests. Mark tests with @pytest.mark.asyncio. Handle coroutines properly. Consider event loop management. Test async contexts, timeouts. Handle async cleanup properly.
Test component interactions, external services. Use appropriate fixtures, mocking selectively. Consider test environment setup. Handle cleanup properly. Balance coverage vs. execution time.
Use fixtures, factory libraries (factory_boy). Consider data isolation, cleanup. Implement proper test data generation. Handle complex data relationships. Consider data versioning, maintenance.
Use caplog fixture in pytest. Verify log messages, levels. Consider log handlers, formatting. Test logger configuration. Handle temporary logger modifications.