7. Testing (pytest)
Write focused tests with fixtures and marks; assert behavior and log output cleanly.
Question: What are some key features of
pytest
that make it so popular?
Answer: pytest
is popular due to its simple assert
statements, powerful fixture system for managing test setup and teardown, and rich plugin ecosystem.
Explanation:
Fixtures:
@pytest.fixture
defines reusable setup code (like a database connection) that can be injected into tests.Parametrization:
@pytest.mark.parametrize
runs the same test with multiple inputs, reducing code duplication.Mocking:
pytest
integrates well withunittest.mock
and plugins likepytest-mock
to make mocking dependencies easy for isolating code under test.
import pytest
@pytest.fixture
def db(tmp_path):
# Setup a temporary test database
return init_db(tmp_path / "test.db")
@pytest.mark.parametrize("email", ["a@b.com", "x@y.org"])
def test_valid_email(email):
assert validate(email)
Question: How do you mock dependencies and environment in
pytest
?
Answer: Use unittest.mock.patch
or the monkeypatch
fixture to replace attributes, environment variables, or functions during a test.
Explanation: Keep tests deterministic by isolating external effects.
from unittest.mock import patch
def test_uses_time():
with patch("module.time.time", return_value=0):
assert compute_timestamp() == 0
def test_env(monkeypatch):
monkeypatch.setenv("APP_ENV", "test")
assert get_env() == "test"
Question: What fixture scopes and auto-use options exist?
Answer: Scopes: function
, class
, module
, package
, session
. Use @pytest.fixture(scope="module", autouse=True)
to apply automatically.
Question: How do you use marks and capture logs?
Answer: Use @pytest.mark.slow
/xfail
to label expectations; use caplog
to assert logs.
import pytest
@pytest.mark.slow
def test_logs(caplog):
with caplog.at_level("INFO"):
run()
assert any("started" in m for m in caplog.messages)
Question: How do you measure test coverage?
Answer: Use pytest-cov
plugin: pytest --cov=your_package --cov-report=term-missing
.
Question: Can you explain the difference between unit, integration, and end-to-end tests?
Answer: Unit tests verify a single, isolated piece of functionality (like a function or a class). Integration tests verify that multiple components work together correctly. End-to-end (E2E) tests verify the entire application flow from the user's perspective.
Explanation:
Unit Tests: Fast and numerous. They mock external dependencies (like databases or APIs) to focus solely on the logic of the unit under test.
Integration Tests: Slower and fewer than unit tests. They test the interaction between components, for example, checking that your application code can correctly query a real (test) database.
E2E Tests: The slowest and fewest. They simulate real user behavior, often by driving a web browser or making real API calls to a deployed environment, to ensure the entire system works as a whole. A healthy test suite has a pyramid shape: many unit tests at the base, fewer integration tests, and even fewer E2E tests at the top.