"""Golden-file comparison, with regeneration that has to be asked for. A golden test is only worth its file if updating that file is a deliberate act. The failure mode this module exists to prevent is the silent self-heal: a comparator that rewrites the reference whenever it disagrees turns every golden into a mirror and every golden test into a no-op. So the rewrite lives behind the ``--update-golden`` flag, and the flag defaults off. The update flag is a parameter rather than something this module reads off the pytest config, so the rewrite path is reachable from an ordinary test without running pytest inside pytest. `tests/conftest.py` binds the flag to the `golden` fixture for callers who want the wiring instead. """ import difflib import os def assert_golden(path, actual, update=False): """Compare ``actual`` against the golden file at ``path``. With ``update`` the file is rewritten and nothing is asserted. Without it, a missing golden and a differing golden both raise, and the message carries a unified diff -- "golden mismatch" on its own sends the reader back to the file to work out what moved. """ if update: with open(path, "w", encoding="utf-8") as handle: handle.write(actual) return if not os.path.exists(path): raise AssertionError( "golden %r does not exist yet. Re-run with --update-golden to " "create it, having first read the output you are blessing." % path ) with open(path, "r", encoding="utf-8") as handle: expected = handle.read() if expected == actual: return diff = "".join( difflib.unified_diff( expected.splitlines(keepends=True), actual.splitlines(keepends=True), fromfile="golden: %s" % path, tofile="actual", ) ) raise AssertionError("golden %r does not match actual output:\n%s" % (path, diff))