[cli-tests] Add --set-exact-output to update the expected output

`./run.py --set-exact-output` will update `stdout.expect` and
`stderr.expect` to match the expected output. This doesn't apply to
outputs which use `.glob` or `.ignore`.
This commit is contained in:
Nick Terrell 2022-12-21 17:21:09 -08:00
parent b6e8112261
commit 7df6e25b85
2 changed files with 25 additions and 3 deletions

View File

@ -45,6 +45,16 @@ Examples:
./run.py --preserve --verbose basic/help.sh ./run.py --preserve --verbose basic/help.sh
``` ```
### Updating exact output
If a test is failing because a `.stderr.exact` or `.stdout.exact` no longer matches, you can re-run the tests with `--set-exact-output` and the correct output will be written.
Example:
```
./run.py --set-exact-output
./run.py basic/help.sh --set-exact-output
```
## Writing a test ## Writing a test
Test cases are arbitrary executables, and can be written in any language, but are generally shell scripts. Test cases are arbitrary executables, and can be written in any language, but are generally shell scripts.

View File

@ -209,6 +209,7 @@ class Options:
preserve: bool, preserve: bool,
scratch_dir: str, scratch_dir: str,
test_dir: str, test_dir: str,
set_exact_output: bool,
) -> None: ) -> None:
self.env = env self.env = env
self.timeout = timeout self.timeout = timeout
@ -216,6 +217,7 @@ class Options:
self.preserve = preserve self.preserve = preserve
self.scratch_dir = scratch_dir self.scratch_dir = scratch_dir
self.test_dir = test_dir self.test_dir = test_dir
self.set_exact_output = set_exact_output
class TestCase: class TestCase:
@ -335,7 +337,7 @@ class TestCase:
self._test_stdin.close() self._test_stdin.close()
self._test_stdin = None self._test_stdin = None
def _check_output_exact(self, out_name: str, expected: bytes) -> None: def _check_output_exact(self, out_name: str, expected: bytes, exact_name: str) -> None:
""" """
Check the output named :out_name: for an exact match against the :expected: content. Check the output named :out_name: for an exact match against the :expected: content.
Saves the success and message. Saves the success and message.
@ -349,6 +351,10 @@ class TestCase:
self._success[check_name] = False self._success[check_name] = False
self._message[check_name] = f"{out_name} does not match!\n> diff expected actual\n{diff(expected, actual)}" self._message[check_name] = f"{out_name} does not match!\n> diff expected actual\n{diff(expected, actual)}"
if self._opts.set_exact_output:
with open(exact_name, "wb") as f:
f.write(actual)
def _check_output_glob(self, out_name: str, expected: bytes) -> None: def _check_output_glob(self, out_name: str, expected: bytes) -> None:
""" """
Check the output named :out_name: for a glob match against the :expected: glob. Check the output named :out_name: for a glob match against the :expected: glob.
@ -386,7 +392,7 @@ class TestCase:
ignore_name = f"{self._test_file}.{out_name}.ignore" ignore_name = f"{self._test_file}.{out_name}.ignore"
if os.path.exists(exact_name): if os.path.exists(exact_name):
return self._check_output_exact(out_name, read_file(exact_name)) return self._check_output_exact(out_name, read_file(exact_name), exact_name)
elif os.path.exists(glob_name): elif os.path.exists(glob_name):
return self._check_output_glob(out_name, read_file(glob_name)) return self._check_output_glob(out_name, read_file(glob_name))
elif os.path.exists(ignore_name): elif os.path.exists(ignore_name):
@ -394,7 +400,7 @@ class TestCase:
self._success[check_name] = True self._success[check_name] = True
self._message[check_name] = f"{out_name} ignored!" self._message[check_name] = f"{out_name} ignored!"
else: else:
return self._check_output_exact(out_name, bytes()) return self._check_output_exact(out_name, bytes(), exact_name)
def _check_stderr(self) -> None: def _check_stderr(self) -> None:
"""Checks the stderr output against the expectation.""" """Checks the stderr output against the expectation."""
@ -678,6 +684,11 @@ if __name__ == "__main__":
"Scratch directory located in TEST_DIR/scratch/." "Scratch directory located in TEST_DIR/scratch/."
) )
) )
parser.add_argument(
"--set-exact-output",
action="store_true",
help="Set stderr.exact and stdout.exact for all failing tests, unless .ignore or .glob already exists"
)
parser.add_argument( parser.add_argument(
"tests", "tests",
nargs="*", nargs="*",
@ -714,6 +725,7 @@ if __name__ == "__main__":
preserve=args.preserve, preserve=args.preserve,
test_dir=args.test_dir, test_dir=args.test_dir,
scratch_dir=scratch_dir, scratch_dir=scratch_dir,
set_exact_output=args.set_exact_output,
) )
if len(args.tests) == 0: if len(args.tests) == 0: