1 The code, with its test
just setupCode and its test arrive together, so the test checks the code from the first day. Read tests/test_count.py,
then count.
uv run python -m unittest discover -s tests -v
git log --oneline --graph --all | head -12Both tests pass. The graph shows the branch parts, which leaves main where the project begins.
Ask: is it easier to read a test before the code, or after?
What changed
.gitignore: New, 10 lines. The file..python-version: New, 1 line. The file.README.md: New, 3 lines. The file.justfile: addsrecipe default,recipe run,recipe setup,recipe test. New, 15 lines. The file.pyproject.toml: New, 14 lines. The file.src/tally/__init__.py:count, which ignores case from the first day, and the command. New, 16 lines. The file.- look at
for word in text.lower().split():
- look at
src/tally/__main__.py: New, 3 lines. The file.tests/test_count.py: a test of counting, and a test of case. New, 11 lines. The file.- look at
self.assertEqual(count("A a"), {"a": 2})
- look at
uv.lock: New, 8 lines. The file.
The diff of .gitignore
@@ -0,0 +1,10 @@
+# Python-generated files
+__pycache__/
+*.py[oc]
+build/
+dist/
+wheels/
+*.egg-info
+
+# Virtual environments
+.venvThe diff of .python-version
@@ -0,0 +1 @@
+3.12The diff of README.md
@@ -0,0 +1,3 @@
+# tally
+
+Count the words in a text.The diff of justfile
@@ -0,0 +1,15 @@
+# The recipes of tally. Each one runs through uv, in the project's own environment.
+default:
+ @just --list
+
+# Make the environment of this step: the first command of every step
+setup:
+ uv sync
+
+# Count the words of a file
+run file:
+ uv run tally {{ file }}
+
+# Run the tests
+test:
+ uv run python -m unittest discover -s tests -qThe diff of pyproject.toml
@@ -0,0 +1,14 @@
+[project]
+name = "tally"
+version = "0.1.0"
+description = "Count the words in a text"
+readme = "README.md"
+requires-python = ">=3.12"
+dependencies = []
+
+[project.scripts]
+tally = "tally:main"
+
+[build-system]
+requires = ["uv_build>=0.12.13,<0.13.0"]
+build-backend = "uv_build"The diff of src/tally/__init__.py
@@ -0,0 +1,16 @@
+"""tally: count the words in a text."""
+
+import sys
+
+
+def count(text):
+ counts = {}
+ for word in text.lower().split():
+ counts[word] = counts.get(word, 0) + 1
+ return counts
+
+
+def main() -> None:
+ text = open(sys.argv[1]).read() if len(sys.argv) > 1 else sys.stdin.read()
+ for word, n in sorted(count(text).items()):
+ print(n, word)The diff of src/tally/__main__.py
@@ -0,0 +1,3 @@
+from tally import main
+
+main()The diff of tests/test_count.py
@@ -0,0 +1,11 @@
+import unittest
+
+from tally import count
+
+
+class Count(unittest.TestCase):
+ def test_words(self):
+ self.assertEqual(count("a b a"), {"a": 2, "b": 1})
+
+ def test_case(self):
+ self.assertEqual(count("A a"), {"a": 2})