Testing⚓︎
PyPDFForm uses pytest for testing and coverage.py for measuring test coverage. To run the tests, execute:
Generate coverage report⚓︎
To generate a test coverage report, run:
View the coverage report by opening htmlcov/index.html in a browser.
View the coverage report at http://localhost:8000/htmlcov/index.html.
Test breakdown⚓︎
Although each PyPDFForm test is unique, most follow a general paradigm.
Most library tests can be summarized in three steps:
- Define the expected PDF file.
- Use PyPDFForm to generate a PDF from the test inputs.
- Compare the PDF generated by the test with the expected PDF file.
Consider this example test:
def test_fill(pdf_samples, request):
expected_path = os.path.join(pdf_samples, "sample_filled.pdf")
with open(expected_path, "rb+") as f:
obj = PdfWrapper(
os.path.join(pdf_samples, "sample_template.pdf")
).fill(
{
"test": "test_1",
"check": True,
"test_2": "test_2",
"check_2": False,
"test_3": "test_3",
"check_3": True,
},
)
request.config.results["expected_path"] = expected_path
request.config.results["stream"] = obj.read()
expected = f.read()
assert len(obj.read()) == len(expected)
assert obj.read() == expected
The test starts by defining an expected PDF sample_filled.pdf:
The test then fills sample_template.pdf with a data dictionary using PdfWrapper:
obj = PdfWrapper(
os.path.join(pdf_samples, "sample_template.pdf")
).fill(
{
"test": "test_1",
"check": True,
"test_2": "test_2",
"check_2": False,
"test_3": "test_3",
"check_3": True,
},
)
Include these two lines in most tests to make expected PDF regeneration easier:
request.config.results["expected_path"] = expected_path
request.config.results["stream"] = obj.read()
Finally, the test compares the generated PDF stream with the expected PDF stream:
Most CLI tests can be summarized in four steps:
- Define the expected PDF file.
- Write any input data required by the command to
tmp_path. - Invoke the CLI command to generate a PDF from the test inputs.
- Compare the PDF generated by the test with the expected PDF file.
Consider this example test:
@pytest.mark.cli_test
def test_fill(pdf_samples, tmp_path):
expected_path = os.path.join(pdf_samples, "docs", "test_fill_text_check.pdf")
input_path = os.path.join(tmp_path, "input.json")
output_path = os.path.join(tmp_path, "output.pdf")
fill_data = {
"test": "test_1",
"check": True,
"test_2": "test_2",
"check_2": False,
"test_3": "test_3",
"check_3": True,
}
with open(input_path, "w") as f:
json.dump(fill_data, f)
result = runner.invoke(
cli_app,
[
"fill",
os.path.join(pdf_samples, "sample_template.pdf"),
"-f",
input_path,
"-o",
output_path,
],
)
assert result.exit_code == 0
with open(expected_path, "rb") as f1, open(output_path, "rb") as f2:
expected = f1.read()
actual = f2.read()
assert len(expected) == len(actual)
assert expected == actual
Mark CLI tests with @pytest.mark.cli_test. The runner is a CliRunner from
typer.testing, and the command under test is the PyPDFForm CLI app:
import pytest
from typer.testing import CliRunner
from PyPDFForm.cli.root import cli_app
runner = CliRunner()
The test starts by defining the expected PDF path, the temporary JSON input path, and the output path:
expected_path = os.path.join(pdf_samples, "docs", "test_fill_text_check.pdf")
input_path = os.path.join(tmp_path, "input.json")
output_path = os.path.join(tmp_path, "output.pdf")
The test then writes the fill dictionary to a JSON file in tmp_path:
fill_data = {
"test": "test_1",
"check": True,
"test_2": "test_2",
"check_2": False,
"test_3": "test_3",
"check_3": True,
}
with open(input_path, "w") as f:
json.dump(fill_data, f)
Next, the test invokes the fill command against sample_template.pdf from pdf_samples:
result = runner.invoke(
cli_app,
[
"fill",
os.path.join(pdf_samples, "sample_template.pdf"),
"-f",
input_path,
"-o",
output_path,
],
)
assert result.exit_code == 0
Finally, the test compares the PDF written by the command with the expected PDF stream: