Testing¶
The fountain-py test suite uses pytest with strict markers and doctest integration.
Coverage is reported as information on every run; there is no threshold to hit.
Parsing and the JSON round trip also carry hypothesis property tests in tests/test_properties.py.
Running Tests¶
# The gate: lint, format check, mypy strict, and tests (module doctests included)
just check
# Tests only
just test
# Tests with HTML coverage report
just test-cov
# Tests on every supported Python version (3.11 through 3.15)
just test-all
# Run a specific test file
uv run pytest tests/test_parser.py
# Run a specific test method
uv run pytest tests/test_edge_cases.py::TestSpecCompliance::test_section_level_1
# Run doctests in source modules
uv run pytest --doctest-modules src/
# Run Sphinx doctests in documentation
just doctest
Test Organization¶
tests/test_parser.py: Core parser featurestests/test_renderer.py: HTML and Fountain renderers (TestHTMLRenderer,TestFountainRenderer)tests/test_document.py: Document analysis methodstests/test_edge_cases.py: Edge cases and spec compliance (TestSpecComplianceclass)tests/test_quickstart_examples.py: Validates all quickstart documentation examplestests/conftest.py: Shared fixtures and sample.fountainfile loading
Writing Tests¶
Follow test-driven development:
RED: Write a failing test that describes the expected behavior
GREEN: Write the minimal code to make it pass
REFACTOR: Clean up while keeping tests green
Guidelines:
Test your logic, not frameworks. Don’t test that pytest works or that Python dicts work.
Test behavior and outcomes, not implementation details.
Spec compliance tests go in
TestSpecComplianceintest_edge_cases.py.Renderer-specific tests go in the appropriate renderer test class in
test_renderer.py.Use descriptive test names that explain the scenario.
Example:
def test_forced_scene_heading_protects_ellipsis(self):
"""Ellipsis at line start should not trigger forced scene heading."""
doc = self.parser.parse("...HELLO")
assert doc.elements[0].type == ElementType.ACTION
Coverage¶
Read coverage as a map of untested paths, not a score to hit.
After running just test-cov, open htmlcov/index.html to view the coverage report.