diff --git a/README.md b/README.md index baeb59e..749ad0a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ Invalid numbers print: invalid ``` +The command exits with status `0` for a valid number and status `1` for an +invalid number, so it can be used directly in shell scripts and CI checks. + Run the test suite: ```bash diff --git a/luhn.py b/luhn.py index c40ae14..ab087ff 100644 --- a/luhn.py +++ b/luhn.py @@ -87,6 +87,7 @@ def append_check_digit(payload: NumberLike) -> str: if __name__ == "__main__": import argparse + import sys parser = argparse.ArgumentParser( description="Validate a number with the Luhn algorithm." @@ -94,4 +95,6 @@ def append_check_digit(payload: NumberLike) -> str: parser.add_argument("number", help="number to validate") args = parser.parse_args() - print("valid" if is_valid(args.number) else "invalid") + valid = is_valid(args.number) + print("valid" if valid else "invalid") + sys.exit(0 if valid else 1) diff --git a/test_luhn.py b/test_luhn.py index b5d0d18..633dede 100644 --- a/test_luhn.py +++ b/test_luhn.py @@ -1,4 +1,7 @@ +import subprocess +import sys import unittest +from pathlib import Path from luhn import append_check_digit, calculate_check_digit, checksum, is_valid @@ -41,6 +44,24 @@ def test_rejects_unsupported_types(self): with self.assertRaises(ValueError): function(value) + def test_cli_exit_status_reflects_validity(self): + script = Path(__file__).with_name("luhn.py") + + for number, expected_output, expected_status in ( + ("79927398713", "valid", 0), + ("79927398714", "invalid", 1), + ): + with self.subTest(number=number): + result = subprocess.run( + [sys.executable, str(script), number], + capture_output=True, + text=True, + check=False, + ) + + self.assertEqual(result.stdout.strip(), expected_output) + self.assertEqual(result.returncode, expected_status) + if __name__ == "__main__": unittest.main()