Install any skill in seconds. Free to start, no credit card required.
Get Started Free →A development process for Python code that uses Test Drivern Development (TDD) to iterate on a new project based around uv. Use when creating a new Python project, writing Python code with tests, or working on Python development using test-driven development practices with the uv package manager.
.claude/skills/gali-leilei-uv-tdd/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | -25% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -13% | 0% |
| case-10 | ✗→✓ | ▲ Improved | -33% | 0% |
| case-14 | ✗→✓ | ▲ Improved | -59% | 0% |
| case-15 | ✗→✓ | ▲ Improved | -46% | 0% |
A development process for Python applications that uses TDD to iterate on a new project based around uv.
Create a project with this command:
bashmkdir name-of-project cd name-of-project uv init --python 3.14 git init (if not already in a git repo)
This creates an initial pyproject.toml file
Add dependencies using:
bashuv add httpx
Always start by adding a dev dependency of pytest like this:
bashuv add pytest --dev
Then add a starting test:
bashmkdir tests echo 'def test_add(): assert 1 + 1 == 2' > tests/test_add.py
Then run the tests like this:
bashuv run pytest
Always run Python code like this:
bashuv run python -c "..."
Always create a README.md for the project, which starts with just the project name as a heading plus a short description.
Start by creating a spec.md file with a detailed specification that includes markdown TODO lists. Update the spec and those TODOs as you progress, including adding new ones and checking off previous ones.
Practice TDD. For every change start by writing a test (grouped sensible in test files with other related tests) and then use uv run pytest -k name_of_test to watch it fail. Then implement the change and watch the test pass. Update the TODOs and add or update relevant documentation in the README, then commit the implementation and tests and documentation as a single commit.
Use and reuse pytest fixtures where appropriate, including for temporary files used for the duration of the test run. Use pytest.mark.parameterized to avoid duplicated test code.
Delete that test_add.py file once you have implemented your first real test. Do not include that test_add.py file in any of your commits.
Commit often, in sensible chunks. If a remote is configured then push after every commit.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 12,471 | 3,128 | -75% | 1 | 1 | 0% | 2,444 | 892 | -64% | 0 | 0 | — |
case-01 | fail→fail | 14,579 | 4,665 | -68% | 1 | 1 | 0% | 3,070 | 679 | -78% | 0 | 0 | — |
case-02 | fail→fail | 14,105 | 9,344 | -34% | 1 | 1 | 0% | 2,653 | 1,456 | -45% | 0 | 0 | — |
case-04 | fail→pass | 10,173 | 4,527 | -55% | 1 | 1 | 0% | 1,733 | 1,305 | -25% | 0 | 0 | — |
case-05 | pass→pass | 5,290 | 2,053 | -61% | 1 | 1 | 0% | 894 | 718 | -20% | 0 | 0 | — |
case-06 | fail→pass | 6,257 | 2,743 | -56% | 1 | 1 | 0% | 1,079 | 941 | -13% | 0 | 0 | — |
case-07 | pass→pass | 4,420 | 1,805 | -59% | 1 | 1 | 0% | 749 | 692 | -8% | 0 | 0 | — |
case-08 | pass→pass | 5,881 | 2,315 | -61% | 1 | 1 | 0% | 854 | 789 | -8% | 0 | 0 | — |
case-09 | fail→fail | 10,748 | 1,827 | -83% | 1 | 1 | 0% | 1,963 | 737 | -62% | 0 | 0 | — |
case-10 | fail→pass | 14,174 | 7,478 | -47% | 1 | 1 | 0% | 2,810 | 1,872 | -33% | 0 | 0 | — |
case-11 | pass→pass | 9,389 | 4,750 | -49% | 1 | 1 | 0% | 1,767 | 1,213 | -31% | 0 | 0 | — |
case-12 | pass→pass | 6,769 | 3,948 | -42% | 1 | 1 | 0% | 1,303 | 1,124 | -14% | 0 | 0 | — |
case-13 | pass→pass | 7,073 | 2,142 | -70% | 1 | 1 | 0% | 1,240 | 763 | -38% | 0 | 0 | — |
case-14 | fail→pass | 11,169 | 2,524 | -77% | 1 | 1 | 0% | 1,880 | 765 | -59% | 0 | 0 | — |
case-15 | fail→pass | 7,262 | 1,508 | -79% | 1 | 1 | 0% | 1,281 | 695 | -46% | 0 | 0 | — |
case-16 | pass→pass | 6,808 | 2,021 | -70% | 1 | 1 | 0% | 1,096 | 773 | -29% | 0 | 0 | — |
case-17 | fail→pass | 12,528 | 6,198 | -51% | 1 | 1 | 0% | 2,116 | 1,568 | -26% | 0 | 0 | — |
case-18 | fail→pass | 5,855 | 1,857 | -68% | 1 | 1 | 0% | 1,061 | 727 | -31% | 0 | 0 | — |
case-19 | fail→pass | 8,975 | 3,610 | -60% | 1 | 1 | 0% | 1,510 | 1,074 | -29% | 0 | 0 | — |
case-20 | pass→pass | 7,409 | 4,737 | -36% | 1 | 1 | 0% | 1,411 | 1,301 | -8% | 0 | 0 | — |
case-21 | pass→pass | 7,130 | 6,149 | -14% | 1 | 1 | 0% | 1,470 | 1,634 | +11% | 0 | 0 | — |
case-22 | pass→pass | 7,959 | 8,570 | +8% | 1 | 1 | 0% | 1,644 | 2,160 | +31% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 21 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.