"""Acceptance test for time-to-green task T04 (pilot-written 2026-10-30; the protocol names it, does not ship it). T04: tally: add a `cols ` subcommand that prints one header name per line; exit 2 on a missing file like the others. Green: python -m unittest tasks.t04_test (run from the repo root) Same assertions as the pilot's copy; the only change for the bench is that the regression suite is now imported from a frozen copy in tasks/ instead of the editable root test file. """ from __future__ import annotations import importlib.util import io import os import tempfile import unittest from tasks.regress_tally import HeadTests, StatsTests # noqa: F401 (collected as regression tests) ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) _spec = importlib.util.spec_from_file_location( "tally_t04", os.path.join(ROOT, "build-a-cli-tool-with-an-agent-from-a-spec.py")) tally = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(tally) def run(argv, text="name,price,qty\nbolt,1.5,10\n"): with tempfile.TemporaryDirectory() as tmp: path = os.path.join(tmp, "data.csv") with open(path, "w", encoding="utf-8", newline="") as fh: fh.write(text) argv = [path if a == "FILE" else a for a in argv] out, err = io.StringIO(), io.StringIO() code = tally.main(argv, out=out, err=err) return code, out.getvalue(), err.getvalue() class ColsTests(unittest.TestCase): def test_cols_prints_one_header_name_per_line(self): code, out, err = run(["cols", "FILE"]) self.assertEqual(code, 0, err) self.assertEqual(out.splitlines(), ["name", "price", "qty"]) def test_cols_missing_file_exits_2(self): out, err = io.StringIO(), io.StringIO() code = tally.main(["cols", "no-such-file.csv"], out=out, err=err) self.assertEqual(code, 2) self.assertEqual(out.getvalue(), "") self.assertIn("cannot read", err.getvalue()) if __name__ == "__main__": unittest.main()