Data#

class safir.testing.data.Data(root, *, update_test_data=False)#

Bases: object

Locate, read, and write test data.

This class provides utility functions to load test data, compare test output against expected output stored in files, and optionally update stored data.

Stored output data (as specified in assert_* methods) will be updated (and thus the assert_* methods will never fail) if the update_test_data constructor argument is True. Generally this should be set by the fixture if the environment variable UPDATE_TEST_DATA is set.

Applications are actively encouraged to subclass this class to add more specific read_*, write_*, and assert_* methods that are specific to the data types used by that application. Those methods should call the methods provided by this base class to perform lower-level operations. In particular, convert objects to JSON and use assert_json_matches or assert_pydantic_matches to compare them so that stored output data updating is properly supported.

Parameters:
  • root (Path) – Path to the root of the test data. Generally this will be discovered based on the path to the conftest.py from which this class is initialized.

  • update_test_data (bool, default: False) – Whether to overwrite expected output in assert_* methods.

Examples

This class is generally created and returned by a fixture in tests/conftest.py such as the following:

import os
from pathlib import Path
from safir.testing.data import Data

@pytest.fixture
def data() -> Data:
    update = bool(os.getenv("UPDATE_TEST_PATH"))
    return Data(Path(__file__).parent / "data", update_test_data=update)

Methods Summary

assert_json_matches(seen, path)

Raise an assertion if the saved expected output doesn't match.

assert_pydantic_matches(seen, path)

Raise an assertion if the saved Pydantic model doesn't match.

assert_text_matches(seen, path)

Raise an assertion if the saved expected output doesn't match.

path(path[, extension])

Construct a path to a test data file.

read_json(path)

Read test data as JSON and return its decoded form.

read_pydantic(model_type, path)

Read test data as a Pydantic model.

read_text(path)

Read test data as text.

write_json(data, path)

Write data as JSON to the test data directory.

write_pydantic(data, path)

Write a Pydantic model as JSON to the test data directory.

write_text(data, path)

Write data as text to the test data directory.

Methods Documentation

assert_json_matches(seen, path)#

Raise an assertion if the saved expected output doesn’t match.

<ANY> strings in the saved expected output are converted to the unittest.mock.ANY wildcard before comparison.

Parameters:
  • seen (Any) – Observed data in the test to be compared.

  • path (str) – Path relative to tests/data of the expected output. A .json extension will be added automatically.

Raises:

AssertionError – Raised if the data doesn’t match.

Return type:

None

assert_pydantic_matches(seen, path)#

Raise an assertion if the saved Pydantic model doesn’t match.

The Pydantic model is serialized to JSON and then compared against the stored JSON serialization, since that produces a better rich diff on mismatch.

This method will miss differences that are not part of the JSON serialization of the model, and only models that can be serialized to JSON can be compared.

Parameters:
  • seen (BaseModel) – Any Pydantic model. The saved data will be presumed to be for the same model.

  • path (str) – Path relative to tests/data of the expected output. A .json extension will be added automatically.

Raises:

AssertionError – Raised if the data doesn’t match.

Return type:

None

assert_text_matches(seen, path)#

Raise an assertion if the saved expected output doesn’t match.

Parameters:
  • seen (str) – Observed data in the test to be compared.

  • path (str) – Path relative to tests/data of the expected output.

Raises:

AssertionError – Raised if the data doesn’t match.

Return type:

None

path(path, extension=None)#

Construct a path to a test data file.

Parameters:
  • path (str) – Path relative to tests/data.

  • extension (str | None, default: None) – Optional extension to add to the file name. If set, the extension will be preceded by a period (.).

Returns:

Full path to file.

Return type:

pathlib.Path

read_json(path)#

Read test data as JSON and return its decoded form.

<ANY> strings in the saved expected output are converted to the unittest.mock.ANY wildcard.

Parameters:

path (str) – Path relative to tests/data. A .json extension will be added automatically.

Returns:

Parsed contents of the file.

Return type:

Any

read_pydantic(model_type, path)#

Read test data as a Pydantic model.

Parameters:
  • path (str) – Path relative to tests/data. A .json extension will be added automatically.

  • model_type (type[TypeVar(T, bound= BaseModel)])

Returns:

Contents of the file validated as a Pydantic model of the given type.

Return type:

pydantic.BaseModel

read_text(path)#

Read test data as text.

Parameters:

path (str) – Path relative to tests/data.

Returns:

Contents of file.

Return type:

str

write_json(data, path)#

Write data as JSON to the test data directory.

Parameters:
  • data (Any) – New data to write.

  • path (str) – Path relative to tests/data of the expected output. A .json extension will be added automatically.

Return type:

None

write_pydantic(data, path)#

Write a Pydantic model as JSON to the test data directory.

Parameters:
  • data (BaseModel) – Pydantic model to write.

  • path (str) – Path relative to tests/data of the expected output. A .json extension will be added automatically.

Return type:

None

write_text(data, path)#

Write data as text to the test data directory.

Parameters:
  • data (str) – New data to write.

  • path (str) – Path relative to tests/data of the expected output.

Return type:

None