"""Acceptance test for time-to-green task T03 (written for the 2026-10-30 bench; the protocol names it, does not ship it). T03: tally: treat cells that are only whitespace or the literal string NA as blank instead of erroring. Green: python -m unittest tasks.t03_test (run from the repo root) "Blank" means what the tool already does with an empty cell: skipped and counted in `blank:`. A column whose cells are all blank-or-NA therefore takes the existing all-blank path (exit 2, "no numeric values"). Other non-numeric text still errors (frozen copy of the shipped suite in tasks/). """ 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_t03", 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): 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 BlankLikeCellTests(unittest.TestCase): def test_whitespace_and_na_cells_count_as_blank(self): code, out, err = run(["stats", "FILE", "--col", "price"], "name,price\na,1\nb, \nc,NA\nd,3\ne, \t \n") self.assertEqual(code, 0, err) self.assertEqual(out, "column: price\ncount: 2\nblank: 3\nmin: 1\n" "max: 3\nmean: 2\nmedian: 2\n") def test_na_only_column_is_the_all_blank_case(self): code, out, err = run(["stats", "FILE", "--col", "price"], "name,price\na,NA\nb,NA\n") self.assertEqual(code, 2) self.assertEqual(out, "") self.assertIn("no numeric values", err) if __name__ == "__main__": unittest.main()