Testing Strategy

Testing patterns and coverage goals

2 min read 341 words

Bengal maintains high code quality through a multi-layered testing strategy with 4,000+ tests.

Test Layers

Unit Tests

Fast & Focused (tests/unit/) Test individual classes/functions. Mock external deps. Target: 90%+ coverage.

Integration Tests

Workflows (tests/integration/) Test subsystem interactions and build flows. Verify cache.

Benchmarks

Performance (tests/performance/) Measure speed on large sites. Catch regressions.

Quick Start

1
2
3
4
5
6
7
8
# Fast feedback loop (recommended during development)
pytest -m "not slow" -n auto  # ~20 seconds

# Unit tests only
pytest tests/unit -n auto  # ~8 seconds

# Full suite
pytest  # ~60 seconds

Test Infrastructure

Test Roots

Minimal, reusable site structures intests/roots/:

Root Purpose Pages
test-basic Minimal smoke test 1
test-directives Card, admonition, glossary 4+
test-navigation Multi-level hierarchy 8
test-large Performance testing 100+
1
2
3
4
@pytest.mark.bengal(testroot="test-directives")
def test_card_directive(site, build_site):
    build_site()
    assert "card-grid" in (site.output_dir / "cards/index.html").read_text()

Canonical Mocks

Use shared mocks instead of inline class definitions:

1
2
3
4
from tests._testing.mocks import MockPage, MockSection, MockSite

page = MockPage(title="Test", url="/test/", tags=["python"])
site = MockSite(pages=[page])

Module-Scoped Fixtures

Rendering tests use module-scoped parser for efficiency:

1
2
3
4
# In tests/unit/rendering/
def test_markdown(parser):  # Parser created once per module
    result = parser.parse("# Hello", {})
    assert "<h1>" in result

Key Testing Patterns

1. Declarative Test Sites

1
2
3
@pytest.mark.bengal(testroot="test-basic", confoverrides={"site.title": "Custom"})
def test_with_overrides(site):
    assert site.title == "Custom"

2. Property-Based Testing

For critical utilities, we usehypothesisto test edge cases (116 tests, 11,600+ examples).

3. Parallel Safety

Mark tests with internal parallelism:

1
2
3
4
@pytest.mark.parallel_unsafe  # Prevents xdist worker crashes
def test_concurrent_operations():
    with ThreadPoolExecutor() as ex:
        ...

Continuous Integration

Every PR runs:

  1. Linting:ruffcheck and format
  2. Type Checking:mypystrict mode
  3. Test Suite: Unit + integration (-m "not slow")
  4. Full Suite: On main/release branches

Seetests/README.mdfor complete documentation.