131 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Trial: stats — Implementation Plan
**Goal:** three-function statistics module used as the SDD trial run (issue #41).
**Spec:** `SPEC.md`.
**Ветка:** `feat/trial`.
> **Пост-фактум (issue #52, O-5).** Это образец, а не протокол прогона. Сам
> прогон выполнен с `describe([1, 2, 3])`, как видно в `reports/review-3.md`;
> после прогона вход теста заменён на несимметричный `[1, 2, 6]`, чтобы
> образец не тиражировал слабость: при таком входе `mean != median`.
## Global Constraints
- Python 3.8+ stdlib only; no dependencies.
- Tests: `python3 -m unittest discover -s tests` from the repository root.
- The implementer of a task makes the commit for that task.
## Task 1: mean
**Files:**
- Create: `src/stats.py`
- Create: `tests/test_stats.py`
**Interfaces:**
- Produces: `mean(values: list[float]) -> float`; `ValueError("empty")` on `[]`.
`src/stats.py`:
```python
"""Small statistics helpers (trial module)."""
def mean(values):
if not values:
raise ValueError("empty")
return float(sum(values)) / len(values)
```
`tests/test_stats.py`:
```python
import unittest
from src.stats import mean
class MeanTest(unittest.TestCase):
def test_mean(self):
self.assertEqual(mean([1, 2, 3]), 2.0)
def test_mean_empty(self):
with self.assertRaises(ValueError):
mean([])
if __name__ == "__main__":
unittest.main()
```
Run: `python3 -m unittest discover -s tests` → 2 tests OK.
Commit: `feat: add mean`.
## Task 2: median
**Files:**
- Modify: `src/stats.py` (append `median`)
- Modify: `tests/test_stats.py` (append `MedianTest`, import `median`)
**Interfaces:**
- Consumes: nothing from Task 1.
- Produces: `median(values: list[float]) -> float`; `ValueError("empty")` on `[]`.
Exact code to append to `src/stats.py`:
```python
def median(values):
xs = sorted(values)
if not xs:
raise ValueError("empty")
n = len(xs)
return float(xs[n // 2])
```
Test to append to `tests/test_stats.py` (class `MedianTest`):
```python
class MedianTest(unittest.TestCase):
def test_median_odd(self):
self.assertEqual(median([3, 1, 2]), 2.0)
def test_median_empty(self):
with self.assertRaises(ValueError):
median([])
```
Run: `python3 -m unittest discover -s tests` → 4 tests OK.
Commit: `feat: add median`.
## Task 3: describe
**Files:**
- Modify: `src/stats.py` (append `describe`)
- Modify: `tests/test_stats.py` (append `DescribeTest`, import `describe`)
**Interfaces:**
- Consumes: `mean` (Task 1), `median` (Task 2).
- Produces: `describe(values: list[float]) -> dict` with keys `count`, `mean`, `median`.
Exact code to append to `src/stats.py`:
```python
def describe(values):
return {"count": len(values), "mean": mean(values), "median": median(values)}
```
Test to append (class `DescribeTest`):
```python
class DescribeTest(unittest.TestCase):
def test_describe(self):
self.assertEqual(
describe([1, 2, 6]),
{"count": 3, "mean": 3.0, "median": 2.0},
)
```
Run: `python3 -m unittest discover -s tests` → 5 tests OK.
Commit: `feat: add describe`.