def compare(
    expected_dir: str,
    actual_dir: str,
    file_pattern: str | None = None,
    actual_extra: bool = False,
    scrubs: list[tuple[str, str]] | None = None,
) -> None:
    """Compare files matching `file_pattern` in `expected_dir` and `actual_dir`.

    `actual_extra` true means `actual_dir` can have extra files in it
    without triggering an assertion.

    `scrubs` is a list of pairs: regexes to find and replace to scrub the
    files of unimportant differences.

    If a comparison fails, a message will be written to stdout, the original
    unscrubbed output of the test will be written to an "/actual/" directory
    alongside the "/gold/" directory, and an assertion will be raised.

    """
    __tracebackhide__ = True    # pytest, please don't show me this function.
    assert os_sep("/gold/") in expected_dir
    assert os.path.exists(actual_dir)
    os.makedirs(expected_dir, exist_ok=True)

    dc = filecmp.dircmp(expected_dir, actual_dir)
    diff_files = _fnmatch_list(dc.diff_files, file_pattern)
    expected_only = _fnmatch_list(dc.left_only, file_pattern)
    actual_only = _fnmatch_list(dc.right_only, file_pattern)

    def save_mismatch(f: str) -> None:
        """Save a mismatched result to tests/actual."""
        save_path = expected_dir.replace(os_sep("/gold/"), os_sep("/actual/"))
        os.makedirs(save_path, exist_ok=True)
        save_file = os.path.join(save_path, f)
        with open(save_file, "w", encoding="utf-8") as savef:
            with open(os.path.join(actual_dir, f), encoding="utf-8") as readf:
                savef.write(readf.read())
                print(os_sep(f"Saved actual output to '{save_file}': see tests/gold/README.rst"))

    # filecmp only compares in binary mode, but we want text mode.  So
    # look through the list of different files, and compare them
    # ourselves.
    text_diff = []
    for f in diff_files:
        expected_file = os.path.join(expected_dir, f)
        with open(expected_file, encoding="utf-8") as fobj:
            expected = fobj.read()
        if expected_file.endswith(".xml"):
            expected = canonicalize_xml(expected)

        actual_file = os.path.join(actual_dir, f)
        with open(actual_file, encoding="utf-8") as fobj:
            actual = fobj.read()
        if actual_file.endswith(".xml"):
            actual = canonicalize_xml(actual)

        if scrubs:
            expected = scrub(expected, scrubs)
            actual = scrub(actual, scrubs)
        if expected != actual:
            text_diff.append(f'{expected_file} != {actual_file}')
            expected_lines = expected.splitlines()
            actual_lines = actual.splitlines()
            print(f":::: diff '{expected_file}' and '{actual_file}'")
            print("\n".join(difflib.Differ().compare(expected_lines, actual_lines)))
            print(f":::: end diff '{expected_file}' and '{actual_file}'")
            print(f"==== expected output in '{os.path.abspath(expected_dir)}'")
            print(f"==== actual output in '{os.path.abspath(actual_dir)}'")
            save_mismatch(f)

    if not actual_extra:
        for f in actual_only:
            save_mismatch(f)

    assert not text_diff, "Files differ: " + "\n".join(text_diff)

    assert not expected_only, f"Files in {os.path.abspath(expected_dir)} only: {expected_only}"
    if not actual_extra:
        assert not actual_only, f"Files in {os.path.abspath(actual_dir)} only: {actual_only}"
Compare files matching `file_pattern` in `expected_dir` and `actual_dir`.

    `actual_extra` true means `actual_dir` can have extra files in it
    without triggering an assertion.

    `scrubs` is a list of pairs: regexes to find and replace to scrub the
    files of unimportant differences.

    If a comparison fails, a message will be written to stdout, the original
    unscrubbed output of the test will be written to an "/actual/" directory
    alongside the "/gold/" directory, and an assertion will be raised.

    
tests/goldtest.py