Package: pytest-snapshot
A plugin for snapshot testing with pytest.This library was inspired byjest’s snapshot testing.
Snapshot testing can be used to test that the value of an expression does not change unexpectedly.
The added benefits of snapshot testing are thatThey are easy to create.They are easy to update when the expected value of a test changes.Instead of manually updating tests when the expected value of an expression changes,
the developer simply needs torunpytest--snapshot-updateto update the snapshot testsverify that the snapshot files contain the new expected resultscommit the snapshot changes to version controlFeaturessnapshot testing of strings and bytessnapshot testing of (optionally nested) collections of strings and bytescomplete control of the snapshot file path and contentRequirementsPython 3.5+ orPyPypytest3.0+InstallationYou can install “pytest-snapshot” viapipfromPyPI:$ pip install pytest-snapshotUsageassert_matchA classic equality test looks like:deftest_function_output():assertfoo('function input')=='expected result'It could be re-written using snapshot testing as:deftest_function_output_with_snapshot(snapshot):snapshot.snapshot_dir='snapshots'# This line is optional.snapshot.assert_match(foo('function input'),'foo_output.txt')The author of the test should thenrunpytest--snapshot-updateto generate the snapshot filesnapshots/foo_output.txtcontaining the output offoo().verify that the content of the snapshot file is valid.commit it to version control.Now, whenever the test is run, it will assert that the output offoo()is equal to the snapshot.What if the behaviour offoo()changes and the test starts to fail?In the first example, the developer would need to manually update the expected result intest_function_output.
This could be tedious if the expected result is large or there are many tests.In the second example, the developer would simplyrunpytest--snapshot-updateverify that the snapshot file contains the new expected resultcommit it to version control.Snapshot testing can be used for expressions whose values are strings or bytes.
For other types, you should first create ahuman readablerepresentation of the value.
For example, to snapshot test ajson-serializablevalue, you could either convert it into json
or preferably convert it into the more readable yaml format usingPyYAML:snapshot.assert_match(yaml.dump(foo()),'foo_output.yml')assert_match_dirWhen snapshot testing acollectionof values,assert_match_dircomes in handy.
It will save a snapshot of a collection of values as a directory of snapshot files.assert_match_dirtakes a dictionary from file name to value.
Dictionaries can also be nested to create nested directories containing snapshot files.For example, the following code creates the directorysnapshots/peoplecontaining filesjohn.jsonandjane.json.deftest_something(snapshot):snapshot.snapshot_dir='snapshots'snapshot.assert_match_dir({'john.json':'{"first name": "John", "last name": "Doe"}','jane.json':'{"first name": "Jane", "last name": "Doe"}',},'people')When runningpytest--snapshot-update, snapshot files will be added, updated, or deleted as necessary.
As a safety measure, snapshots will only be deleted when using the--allow-snapshot-deletionflag.Common use caseA quick way to create snapshot tests is to create a directory containing many test case directories.
In each test case, add files containing the inputs to the function you wish to test.
For example:test_cases
    case1
        input.json
    case2
        input.json
    ...Next, add a test that is parametrized on all test case directories. The test shouldread input from the test case directorycall the function to be testedsnapshot the result to the test case directoryimportjsonimportosimportpytestimportyamlfrompathlibimportPathdefjson_to_yaml(json_string):obj=json.loads(json_string)returnyaml.dump(obj,indent=2)@pytest.mark.parametrize('case_dir',list(Path('test_cases').iterdir()))deftest_json(case_dir,snapshot):# Read input files from the case directory.input_json=case_dir.joinpath('input.json').read_text()# Call the tested function.output_yaml=json_to_yaml(input_json)# Snapshot the return value.snapshot.snapshot_dir=case_dirsnapshot.assert_match(output_yaml,'output.yml')Now, we can runpytest--snapshot-updateto create anoutput.ymlsnapshot for each test case.
If we later decide to modify the tested function’s behaviour,
we can fix the test cases with anotherpytest--snapshot-update.Similar PackagesAnother python package that can be used for snapshot testing issnapshottest.
While this package and snapshottest fulfill the same role, there are some differences.With pytest-snapshot:Every snapshot is saved to a separate file.The paths to snapshot files are fully customizable.The serialization of objects to snapshots is fully customizable (the library does not serialize).This allows the user to organize snapshots in the most human-readable and logical place in their code repository.
This is highly beneficial since snapshots will be viewed by users many times during development and code reviews.ContributingContributions are very welcome. Before contributing, please discuss the change with me.
I wish to keep this plugin flexible and not enforce any project layout on the user.Tests can be run withtoxorpython-mpytest.
Note that the test suite does not pass when run with--assert=plain.LicenseDistributed under the terms of theMITlicense, “pytest-snapshot” is free and open source software.IssuesIf you encounter any problems, pleasefile an issuealong with a detailed description.LinksReleases:https://pypi.org/project/pytest-snapshot/Code:https://github.com/joseph-roitman/pytest-snapshotThispytestplugin was generated withCookiecutteralong with@hackebrot’scookiecutter-pytest-plugintemplate.