> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Driven Development with Claude

> Demonstrates a TDD workflow using an LLM to generate pytest tests, implement a Python unit converter, run tests, and resolve floating point precision edge cases.

In this lesson you'll see a practical TDD (Test-Driven Development) workflow accelerated by an LLM-based code assistant. We generate a full pytest test suite for a small Python "Unit Converter" utility, run the tests (red), implement the module to satisfy them (green), and handle a real-world precision edge case that required human judgment.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/Xs8Ruv7b0QCZf7iM/images/Claude-Code-for-Beginners/Advanced-Features/Test-Driven-Development-with-Claude/test-driven-development-claude-demo-kodekloud.jpg?fit=max&auto=format&n=Xs8Ruv7b0QCZf7iM&q=85&s=5e817f6c1b6431eec94d83e764a2eae1" alt="A presentation slide titled &#x22;Test-Driven Development with Claude&#x22; with a dark teardrop-shaped design on the right containing the word &#x22;Demo.&#x22; The bottom-left corner shows a small &#x22;© Copyright KodeKloud&#x22; notice." width="1920" height="1080" data-path="images/Claude-Code-for-Beginners/Advanced-Features/Test-Driven-Development-with-Claude/test-driven-development-claude-demo-kodekloud.jpg" />
</Frame>

Why this matters: TDD is powerful when applied consistently. LLM-based assistants speed up the specification and test generation steps, but you still need to run tests, inspect failures, and make precise human decisions for numerical correctness and edge cases.

Overview

* Create a small Python project: a Unit Converter module.
* Use an LLM-based code assistant to produce a robust pytest suite (`test_converter.py`).
* Run tests (expected to fail initially because `converter.py` is missing).
* Implement `converter.py` to satisfy tests.
* Iterate until all tests pass; investigate any precision failures and decide whether to change constants, test tolerances, or implementation rounding.

Initial project state

* Virtual environment active (Python 3).
* File `test_converter.py` created by an LLM from a detailed prompt (implementation intentionally omitted).

Example prompt used to generate tests (trimmed)

```text theme={null}
You are an expert Python developer practicing test-driven development.
Your first task is to write a complete and robust pytest test suite for a new module, converter.py.
Do not write the implementation code for the functions. Your sole responsibility is to generate pytest tests.

Project: Unit Converter Module

Functional Requirements:
- Each function accepts a single numeric argument (int or float) and returns a float.

Distance Conversions:
  - miles_to_kilometers(miles) — 1 mile = 1.60934 kilometers
  - kilometers_to_miles(km) — 1 kilometer = 0.621371 miles

Volume Conversions:
  - gallons_to_liters(gallons) — US gallon to liters
  - liters_to_gallons(liters) — liters to US gallons

Mass Conversions:
  - pounds_to_kilograms(pounds)
  - kilograms_to_pounds(kg)

Temperature Conversions:
  - fahrenheit_to_celsius(fahrenheit)
  - celsius_to_fahrenheit(celsius)

Test expectations:
- Correctness tests with integer and floating inputs.
- Edge cases: 0 and negative numbers.
- Error handling: non-numeric input should raise TypeError (use pytest.raises).
- Use pytest.approx() where appropriate for floating point comparisons.
```

What the generated tests looked like (structure, trimmed)

```python theme={null}
# test_converter.py
import pytest
from converter import (
    miles_to_kilometers,
    kilometers_to_miles,
    gallons_to_liters,
    liters_to_gallons,
    pounds_to_kilograms,
    kilograms_to_pounds,
    fahrenheit_to_celsius,
    celsius_to_fahrenheit
)

class TestDistanceConversions:
    def test_miles_to_kilometers_positive_integer(self):
        assert miles_to_kilometers(1) == pytest.approx(1.60934)
        assert miles_to_kilometers(5) == pytest.approx(8.0467)

    def test_miles_to_kilometers_float(self):
        assert miles_to_kilometers(2.5) == pytest.approx(4.02335)

    def test_miles_to_kilometers_zero(self):
        assert miles_to_kilometers(0) == pytest.approx(0.0)

    def test_miles_to_kilometers_negative(self):
        assert miles_to_kilometers(-3) == pytest.approx(-4.82802)

    def test_miles_to_kilometers_type_error(self):
        with pytest.raises(TypeError):
            miles_to_kilometers("test")
# ... similar classes for volume, mass, temperature
```

Running the tests before implementation

* With only `test_converter.py` present (no `converter.py`), pytest fails at collection:

```text theme={null}
==================================== ERRORS ====================================
ERROR collecting test_converter.py
ImportError while importing test module '.../test_converter.py'.
E   ModuleNotFoundError: No module named 'converter'
============================= short test summary info =============================
ERROR test_converter.py
============================= 1 error in 0.07s
```

This is the expected TDD "red" phase: tests fail because the implementation is missing.

Implementing `converter.py`

Requirements for each function:

* Validate input is numeric (int or float). If not, raise `TypeError`.
* Return the converted value as a float.
* Prefer well-known constants for conversions to avoid unnecessary precision disagreements.

Reference table of functions and conversion constants

| Function | Purpose | Recommended constant / note |
| - | - | - |
| `miles_to_kilometers(miles)` | Miles → Kilometers | Multiply by `1.60934` |
| `kilometers_to_miles(km)` | Kilometers → Miles | Multiply by `0.621371` |
| `gallons_to_liters(gallons)` | US Gallons → Liters | Multiply by `3.785411784` |
| `liters_to_gallons(liters)` | Liters → US Gallons | Multiply by `0.2641720523581484` |
| `pounds_to_kilograms(pounds)` | Pounds → Kilograms | Multiply by `0.45359237` |
| `kilograms_to_pounds(kg)` | Kilograms → Pounds | Multiply by `2.2046226218487757` |
| `fahrenheit_to_celsius(fahrenheit)` | °F → °C | `(fahrenheit - 32) * 5.0 / 9.0` |
| `celsius_to_fahrenheit(celsius)` | °C → °F | `celsius * 9.0 / 5.0 + 32` |

Recommended implementation (clean, precise)

```python theme={null}
def _validate_numeric(value, name="Input"):
    if not isinstance(value, (int, float)):
        raise TypeError(f"{name} was not a numeric value")


def miles_to_kilometers(miles):
    """Converts miles to kilometers."""
    _validate_numeric(miles, "miles")
    return miles * 1.60934


def kilometers_to_miles(km):
    """Converts kilometers to miles."""
    _validate_numeric(km, "km")
    return km * 0.621371


def gallons_to_liters(gallons):
    """Converts US gallons to liters."""
    _validate_numeric(gallons, "gallons")
    # 1 US gallon = 3.785411784 liters (exact)
    return gallons * 3.785411784


def liters_to_gallons(liters):
    """Converts liters to US gallons."""
    _validate_numeric(liters, "liters")
    # reciprocal of 3.785411784
    return liters * 0.2641720523581484


def pounds_to_kilograms(pounds):
    """Converts pounds to kilograms."""
    _validate_numeric(pounds, "pounds")
    # 1 pound = 0.45359237 kilograms (exact)
    return pounds * 0.45359237


def kilograms_to_pounds(kg):
    """Converts kilograms to pounds."""
    _validate_numeric(kg, "kg")
    # reciprocal of 0.45359237
    return kg * 2.2046226218487757


def fahrenheit_to_celsius(fahrenheit):
    """Converts degrees Fahrenheit to Celsius."""
    _validate_numeric(fahrenheit, "fahrenheit")
    return (fahrenheit - 32) * 5.0 / 9.0


def celsius_to_fahrenheit(celsius):
    """Converts degrees Celsius to Fahrenheit."""
    _validate_numeric(celsius, "celsius")
    return celsius * 9.0 / 5.0 + 32
```

Running pytest after implementation

* After implementing `converter.py`, run:

```bash theme={null}
python3 -m pytest -v
```

* In the demo workflow this produced 39 passing tests and 1 failure. The failing test revealed a small precision mismatch in the gallons-to-liters expectation:

```text theme={null}
collected 40 items
.......................................F
================================== FAILURES ==================================
________________ TestVolumeConversions.test_gallons_to_liters_float ________________
E       comparison failed
E       Obtained: 10.4098775
E       Expected: 10.409778 ± 1.0e-05

1 failed, 39 passed in 0.05s
```

Precision and the LLM "endless edit" loop

* LLMs are excellent at producing tests and starter code, but they can trigger small regression cycles: you tweak a constant or rounding to satisfy one test and then break another test. These oscillations require human decisions:
  * Should the implementation use a specific authoritative constant?
  * Is the test tolerance too strict (adjust pytest.approx)?
  * Is rounding required for business logic?

<Callout icon="lightbulb" color="#1CB2FE">
  Note: numerical conversions depend on chosen constants and tolerances. Prefer matching documented constants and using `pytest.approx()` in tests with a reasonable tolerance. Avoid introducing ad-hoc conditional logic in the implementation to satisfy a single test.
</Callout>

Recommendations and practical workflow tips

* Use an LLM-based assistant to accelerate test generation from a clear, precise prompt.
* Run tests locally as part of the TDD loop: write (or generate) tests, run them, implement the minimal code to pass, iterate.
* For floating point comparisons:
  * Use authoritative physical constants where available.
  * Use `pytest.approx()` with an appropriate tolerance rather than tight equality.
  * If a business requirement dictates strict rounding, document it and implement rounding explicitly.
* Expect to intervene when the LLM's automated edits produce regressions—this is part of normal engineering judgment.

Conclusion

* LLM-based tools are powerful for generating tests and scaffolding implementations, but treat their output as a solid starting point, not a final answer.
* Follow core TDD steps:
  1. Write/generate tests first.
  2. Run tests and see failures.
  3. Implement minimally to satisfy tests.
  4. Iterate until passing, paying attention to numerical precision and test quality.
* Human review is essential for precision, edge cases, and architectural choices.

Links and references

* pytest documentation: [https://docs.pytest.org/en/stable/](https://docs.pytest.org/en/stable/)
* Python packaging and virtual environments: [https://packaging.python.org/](https://packaging.python.org/)
* Conversion constants reference (examples): NIST or other authoritative sources

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/claude-code-for-beginners/module/a295c914-f61e-47bb-8adc-7a3145745aa6/lesson/afd1bb19-60e7-4184-b98b-45e624967de4" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.