Download tests/test_cli.py from DBax127/nexa: direct link, hf CLI and curl.
- Browser
- Download file 13.2 kB
-
https://huggingface.co/DBax127/nexa/resolve/main/tests/test_cli.py
- Command line
-
hf download hf://DBax127/nexa/tests/test_cli.py
-
curl -L -o test_cli.py https://huggingface.co/DBax127/nexa/resolve/main/tests/test_cli.py
13.2 kB
| """The exit-code contract, and the banner that should appear exactly once. | |
| Exit codes are three-valued on purpose: 0 worked, 1 the command ran and | |
| reported findings, 2 it was called wrong. Before that split, `nexa ask` with no | |
| question printed help and returned 0 -- so `nexa ask odoo "$Q" || exit 1` | |
| reported success for an empty $Q. Every row of the table below is a contract, | |
| and the comments mark the ones that used to return the wrong number. | |
| Most of these call main() in-process: it returns the code rather than exiting, | |
| so the assertion is direct, it runs in milliseconds, and a coverage run can | |
| actually see the branches being taken. A handful go through a real subprocess at | |
| the bottom, because in-process calls would never catch a broken __main__ block. | |
| """ | |
| import os | |
| import subprocess | |
| import sys | |
| import pytest | |
| import nexa | |
| ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| OK, FINDINGS, MISUSE = 0, 1, 2 | |
| def fresh_banner(monkeypatch): | |
| """banner(once=True) is process-global, and every test here is a new run.""" | |
| monkeypatch.setattr(nexa, "_BANNER_SHOWN", False) | |
| def in_repo(monkeypatch): | |
| """nexa resolves the corpus relative to its own file, but check and index | |
| take paths from the caller's working directory.""" | |
| monkeypatch.chdir(ROOT) | |
| def main(*args): | |
| return nexa.main(list(args)) | |
| def shell(*args): | |
| proc = subprocess.run([sys.executable, os.path.join(ROOT, "nexa.py")] + list(args), | |
| capture_output=True, text=True, encoding="utf-8", | |
| errors="replace", cwd=ROOT) | |
| return proc.returncode, (proc.stdout or "") | |
| CASES = [ | |
| ([], OK, "bare invocation prints the command list"), | |
| (["version"], OK, "machine-readable, and the one command with no banner"), | |
| (["--version"], OK, "the flag spelling"), | |
| (["help"], OK, "help with no topic is the command list"), | |
| (["help", "ask"], OK, "help for a real command"), | |
| (["help", "bogus"], MISUSE, "was 1: an unknown topic is misuse, not a finding"), | |
| (["bogus"], MISUSE, "was 1"), | |
| (["ask"], MISUSE, "was 0 -- the bug that motivated the split"), | |
| (["ask", "odoo"], MISUSE, "was 0: a stack with no question is still misuse"), | |
| (["run"], MISUSE, "was 0"), | |
| (["run", "odoo"], MISUSE, "was 0"), | |
| (["index"], MISUSE, "was 0"), | |
| (["check"], MISUSE, "was 0"), | |
| (["check", "no_such_file_here.py"], MISUSE, "was 1: a bad path is a bad argument"), | |
| (["rules"], OK, "the whole corpus"), | |
| (["rules", "onchange"], OK, "a term that matches"), | |
| (["rules", "zzzznomatch"], FINDINGS, "ran fine, found nothing -- NOT misuse"), | |
| (["rules", "--stack", "odoo"], OK, "the one stack, named"), | |
| (["rules", "--full", "odoo.onchange-is-not-validation"], OK, "a real id"), | |
| (["rules", "--full", "no.such.rule"], MISUSE, "was 1: an id that does not exist"), | |
| (["validate"], OK, "corpus is schema-valid"), | |
| (["crosscheck"], OK, "informational, never fails the build"), | |
| (["coverage"], OK, "reports its own blind spots"), | |
| (["adversarial"], OK, "all three probes"), | |
| (["adversarial", "evasion"], OK, "one probe by name"), | |
| ] | |
| def test_exit_code(args, expected, why, capsys): | |
| assert main(*args) == expected, "{0}: {1}".format(" ".join(args) or "(none)", why) | |
| def test_empty_search_and_bad_id_are_different_codes(capsys): | |
| """The distinction the three-valued scheme exists for: 'I looked and found | |
| nothing' is a result; 'that id does not exist' is a mistake.""" | |
| assert main("rules", "zzzznomatch") == FINDINGS | |
| assert main("rules", "--full", "no.such.rule") == MISUSE | |
| def test_usage_error_still_shows_the_help_text(capsys): | |
| """Exiting non-zero is no reason to withhold the thing the user needs. | |
| Asserted against the usage string the command actually declares, rather | |
| than a copy of it: this used to spell out the stack list and went red when | |
| a fourth stack was added, which is not what it is testing. | |
| """ | |
| assert main("ask") == MISUSE | |
| assert nexa.COMMANDS["ask"][1] in capsys.readouterr().out | |
| def test_unknown_command_points_back_at_the_command_list(capsys): | |
| for args in (["bogus"], ["help", "bogus"]): | |
| nexa._BANNER_SHOWN = False | |
| main(*args) | |
| out = capsys.readouterr().out | |
| assert "unknown command" in out | |
| assert "for the command list" in out, "both spellings give the same hint" | |
| def test_commands_table_and_dispatch_agree(capsys): | |
| """A command listed in help with no dispatch branch would print its help and | |
| then fall through to 'unknown command'.""" | |
| for name in nexa.COMMANDS: | |
| nexa._BANNER_SHOWN = False | |
| assert main("help", name) == OK | |
| assert "unknown command" not in capsys.readouterr().out | |
| # ---------------------------------------------------------------- the banner | |
| def test_banner_prints_once_per_process(capsys): | |
| nexa.banner(subtitle=False, once=True) | |
| nexa.banner(subtitle=False, once=True) | |
| assert capsys.readouterr().out.count("NEXA") == 1 | |
| def test_banner_without_once_always_prints(capsys): | |
| nexa.banner(subtitle=False) | |
| nexa.banner(subtitle=False) | |
| assert capsys.readouterr().out.count("NEXA") == 2 | |
| def test_every_command_wears_the_banner(capsys): | |
| for args in (["rules"], ["validate"], ["coverage"], ["adversarial"], ["bogus"]): | |
| nexa._BANNER_SHOWN = False | |
| main(*args) | |
| assert "NEXA" in capsys.readouterr().out, "{0} printed no banner".format(args) | |
| def test_version_is_the_one_command_without_a_banner(capsys): | |
| main("version") | |
| out = capsys.readouterr().out | |
| assert out.strip() == "nexa {0}".format(nexa.VERSION) | |
| # ------------------------------------------------------ the real entry point | |
| def test_subprocess_entry_point_exits_with_the_returned_code(): | |
| """In-process tests never execute the __main__ block, so sys.exit(main()) | |
| and the KeyboardInterrupt handler around it would go unchecked.""" | |
| assert shell("version")[0] == OK | |
| assert shell("bogus")[0] == MISUSE | |
| assert shell("ask")[0] == MISUSE | |
| def test_subprocess_version_is_parseable(): | |
| code, out = shell("version") | |
| assert code == OK | |
| assert out.strip() == "nexa {0}".format(nexa.VERSION) | |
| def test_subprocess_output_is_clean_when_not_a_terminal(): | |
| """Piped output must carry no escape codes: COLOR is gated on isatty, and a | |
| redirect that captured raw ANSI would make `nexa rules > file` unreadable.""" | |
| code, out = shell("rules", "onchange") | |
| assert code == OK | |
| assert "\033" not in out | |
| # --------------------------------------------- the wordmark and its underbar | |
| def _art_rows(art): | |
| """The art's rows, indentation intact, without the blank lines the triple- | |
| quoted literal starts and ends with.""" | |
| return [row for row in art.splitlines() if row.strip()] | |
| def test_both_spellings_are_the_same_height(): | |
| """banner() bands by row index, so a fallback of a different height would | |
| paint the bar as a letterform and vice versa.""" | |
| assert len(_art_rows(nexa.BANNER_UNICODE)) == len(_art_rows(nexa.BANNER_ASCII)) | |
| # The wordmark, and the bar under it. | |
| assert len(_art_rows(nexa.BANNER_UNICODE)) == nexa.BANNER_ROWS + 1 | |
| def test_the_bar_is_as_wide_as_the_wordmark(): | |
| """The bar is light thrown by the sign. One that overhangs the letters, or | |
| falls short of them, reads as a rule somebody drew underneath instead.""" | |
| for art in (nexa.BANNER_UNICODE, nexa.BANNER_ASCII): | |
| widths = set(len(row) for row in _art_rows(art)) | |
| assert len(widths) == 1, art | |
| def test_the_ascii_fallback_is_actually_ascii(): | |
| """It exists for a console on a legacy code page. A block-drawing character | |
| surviving into it defeats the entire point.""" | |
| assert nexa.BANNER_ASCII.isascii() | |
| def test_glyphs_lists_every_non_ascii_character_the_module_can_print(): | |
| """GLYPHS is what _enable_utf8 probes a declared encoding with. | |
| A glyph added to the UI and not to GLYPHS makes the probe pass on an | |
| encoding that cannot hold it, and the character reaches the terminal | |
| anyway -- the exact crash the fallback exists to prevent, reintroduced one | |
| character at a time. Asserted against the source rather than against the | |
| constants, because those are already degraded to ASCII when UNICODE is | |
| False and would have nothing to say in the run that matters. | |
| Comments are excluded. They are never printed, and the ones describing the | |
| bar name the very characters this is looking for. | |
| """ | |
| import io | |
| import tokenize | |
| with open(os.path.join(ROOT, "nexa.py"), encoding="utf-8") as handle: | |
| source = handle.read() | |
| printable = set() | |
| for token in tokenize.generate_tokens(io.StringIO(source).readline): | |
| if token.type == tokenize.COMMENT: | |
| continue | |
| printable.update(ch for ch in token.string if ord(ch) > 127) | |
| assert printable, "the scan found nothing, so it is not reading the art" | |
| missing = sorted(printable - set(nexa.GLYPHS)) | |
| assert not missing, "used but not in nexa.GLYPHS: " + " ".join(missing) | |
| def _cube(n): | |
| """An xterm-256 cube index as its (r, g, b) coordinates, each 0-5.""" | |
| n -= 16 | |
| return (n // 36, (n % 36) // 6, n % 6) | |
| def test_the_ramp_sweeps_cyan_to_magenta(): | |
| """Endpoints, asserted against the NUMBERS rather than the escape codes. | |
| Under NO_COLOR every code is the empty string, so a test written against | |
| codes would pass for any ramp at all, which is worse than not testing it. | |
| """ | |
| assert nexa.BANNER_RAMP[0] == 51, "starts on cyan" | |
| assert nexa.BANNER_RAMP[-1] == 201, "ends on magenta" | |
| assert nexa.BANNER_BAR == 214, "amber, what the rest of the CLI warns in" | |
| assert nexa.BANNER_BAR not in nexa.BANNER_RAMP, ( | |
| "the bar contrasts with the wordmark rather than continuing it") | |
| def test_the_steps_between_are_an_interpolation_not_a_shortlist(): | |
| """The whole claim of a ramp. Cyan to magenta the short way round holds | |
| blue at maximum while red rises and green falls; a colour picked because | |
| somebody liked it breaks one of those three, and the gradient develops a | |
| kink no amount of squinting at a screenshot reliably catches.""" | |
| steps = [_cube(n) for n in nexa.BANNER_RAMP] | |
| assert all(b == 5 for _r, _g, b in steps), steps | |
| reds = [r for r, _g, _b in steps] | |
| greens = [g for _r, g, _b in steps] | |
| assert reds == sorted(reds), "red must rise monotonically" | |
| assert greens == sorted(greens, reverse=True), "green must fall monotonically" | |
| assert len(set(nexa.BANNER_RAMP)) == len(nexa.BANNER_RAMP), ( | |
| "two rows sharing a colour is a ramp with a step missing") | |
| def test_the_readme_shows_the_banner_that_ships(): | |
| """The README drifted silently once already -- it was still showing an | |
| outlined NX after the art had changed twice, and that stale block reached | |
| two public remotes before anybody noticed. A wordmark in the README is a | |
| claim about what the command prints, so it is the same art or it is wrong.""" | |
| path = os.path.join(ROOT, "README.md") | |
| with open(path, encoding="utf-8") as handle: | |
| readme = handle.read() | |
| for row in _art_rows(nexa.BANNER_UNICODE): | |
| assert row in readme, "README is missing this row of the wordmark: " + row | |
| def test_the_rendered_palette_is_built_from_the_ramp(): | |
| """And the codes that reach the terminal come from those numbers rather than | |
| from a second, hand-kept list that can drift from them.""" | |
| assert nexa.WORDMARK_GRADIENT == [nexa.c(n) for n in nexa.BANNER_RAMP] | |
| assert nexa.BAR_COLOUR == nexa.c(nexa.BANNER_BAR) | |
| def test_the_wordmark_row_count_matches_the_hue_count(): | |
| """One hue per letterform row. If they drift, the banding wraps and two rows | |
| share a colour.""" | |
| assert len(nexa.WORDMARK_GRADIENT) == nexa.BANNER_ROWS | |
| def test_the_banner_prints_once_in_a_real_run(): | |
| """`python nexa.py` leaves the name `nexa` unclaimed, so nexa_cmds doing | |
| `import nexa` loaded a SECOND copy of the module -- with its own COLOR, its | |
| own UNICODE and its own _BANNER_SHOWN. banner(once=True) then printed twice | |
| on `doctor` and `build`, each copy believing it was the first. | |
| Only a subprocess can see this. Under pytest the module is imported once | |
| under its own name, the two never diverge, and the test above passes while | |
| the CLI prints two banners. | |
| """ | |
| _, out = shell("doctor") | |
| assert out.count("validation intelligence") == 1, out | |
| def test_the_banner_says_whose_work_it_is(capsys): | |
| """The byline rides under the wordmark on every command that prints one, | |
| including the short form. Read from the same two constants the README | |
| footer and LICENSE spell out, so the three cannot drift apart.""" | |
| nexa.banner(subtitle=False) | |
| out = capsys.readouterr().out | |
| assert "created by " + nexa.AUTHOR in out | |
| assert nexa.YEAR in out | |
| def test_version_stays_bare(capsys): | |
| """The byline must not reach the one line a script parses.""" | |
| assert nexa.main(["version"]) == 0 | |
| assert capsys.readouterr().out.strip() == "nexa " + nexa.VERSION | |