| name | python-testing |
| description | Unit testing framework for Python using pytest. Use when writing test cases, validating code behavior, checking test coverage, or debugging test failures. |
Python Testing
Unit testing and test coverage with pytest.
Installation
pip install pytest pytest-cov
Quick Start
# test_example.py
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
Run tests:
pytest test_example.py
pytest -v # verbose output
Test Organization
# Group related tests in classes
class TestLexer:
def test_tokenize_number(self):
lexer = Lexer("123")
tokens = lexer.tokenize()
assert tokens[0].type == "NUMBER"
assert tokens[0].value == "123"
def test_tokenize_identifier(self):
lexer = Lexer("foo")
tokens = lexer.tokenize()
assert tokens[0].type == "IDENTIFIER"
Fixtures and Setup
import pytest
@pytest.fixture
def lexer():
"""Reusable lexer instance."""
return Lexer()
@pytest.fixture
def sample_code():
return "func add(a: int, b: int) -> int { return a + b; }"
def test_with_fixtures(lexer, sample_code):
tokens = lexer.tokenize(sample_code)
assert len(tokens) > 0
Test Coverage
# Run with coverage report
pytest --cov=mymodule tests/
# Generate HTML coverage report
pytest --cov=mymodule --cov-report=html tests/
# Check coverage threshold
pytest --cov=mymodule --cov-fail-under=80 tests/
Parametrized Tests
@pytest.mark.parametrize("input,expected", [
("123", "NUMBER"),
("foo", "IDENTIFIER"),
("+", "PLUS"),
("->", "ARROW"),
])
def test_token_types(input, expected):
lexer = Lexer(input)
tokens = lexer.tokenize()
assert tokens[0].type == expected
Exception Testing
def test_syntax_error():
parser = Parser(tokens)
with pytest.raises(SyntaxError) as exc:
parser.parse()
assert "unexpected token" in str(exc.value)
Test Discovery
Pytest automatically discovers tests that follow naming conventions:
- Test files:
test_*.pyor*_test.py - Test functions:
test_* - Test classes:
Test*
Common Patterns
# Test multiple conditions
def test_parser_output():
ast = parse("func main() -> int { return 42; }")
assert ast["type"] == "Program"
assert len(ast["functions"]) == 1
assert ast["functions"][0]["name"] == "main"
# Test file output
def test_codegen_output(tmp_path):
output_file = tmp_path / "output.wat"
codegen = CodeGenerator()
codegen.generate(ast, str(output_file))
content = output_file.read_text()
assert "(module" in content
assert "(func $main" in content