Add testing policy contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
82
rules/patterns/testing-policy/contract.md
Normal file
82
rules/patterns/testing-policy/contract.md
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Contract: Testing Policy
|
||||||
|
|
||||||
|
Version: 1.0
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Определяет когда писать тесты, когда не писать, и как их поддерживать.
|
||||||
|
Применяется ко всем проектам на Go. Агенты следуют этим правилам самостоятельно, без запроса подтверждения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Когда тест обязателен
|
||||||
|
|
||||||
|
Тест пишется всегда, когда код делает нетривиальное преобразование данных или реализует бизнес-логику:
|
||||||
|
|
||||||
|
- **Парсеры** — любой код, читающий внешний формат (XML, JSON, CSV, бинарный)
|
||||||
|
- **Трансформации** — конвертация единиц, нормализация, маппинг полей
|
||||||
|
- **Бизнес-правила** — расчёты, фильтрация, агрегация, приоритизация
|
||||||
|
- **Граничные случаи** — пустой ввод, нулевые значения, переполнение, отсутствующие поля
|
||||||
|
- **Регрессии** — если баг был найден, тест фиксирует его до исправления
|
||||||
|
|
||||||
|
Тест пишется в том же коммите, что и функциональность. Функциональность без теста (там где он обязателен) — неполный коммит.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Когда тест не нужен
|
||||||
|
|
||||||
|
Тест не пишется на код, где он не даёт ценности:
|
||||||
|
|
||||||
|
- Геттеры и сеттеры: `func (s *Server) Port() int { return s.port }`
|
||||||
|
- Конфиг-структуры и константы
|
||||||
|
- Тривиальный клей: передача параметров, инициализация, dependency wiring
|
||||||
|
- Логирование и форматирование вывода
|
||||||
|
- HTTP-хендлеры без бизнес-логики (только роутинг и вызов сервиса)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Структура теста
|
||||||
|
|
||||||
|
Использовать стандартный Go `testing`. Табличные тесты (`[]struct{ ... }`) — когда случаев больше двух.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TestParseGPUSensor(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
xml string
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{"normal", `<VALUE>290</VALUE>`, 29},
|
||||||
|
{"zero", `<VALUE>0</VALUE>`, 0},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := parseGPUTemp(tt.xml)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Fatalf("got %d, want %d", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Фикстуры (XML, JSON, бинарные данные) — инлайн-константы или файлы в `testdata/`.
|
||||||
|
Не использовать реальные сетевые вызовы и реальную БД в юнит-тестах.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Мейнтейнс
|
||||||
|
|
||||||
|
- Сломанный тест — чинится или удаляется в том же коммите где сломался.
|
||||||
|
- Закомментированный тест — не допускается. Если тест неактуален — удалить.
|
||||||
|
- Тест, проверяющий удалённую функциональность — удалить вместе с функциональностью.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Инструкция для агентов (Codex, Claude)
|
||||||
|
|
||||||
|
1. При добавлении функциональности — проверь по списку выше, попадает ли код в категорию "обязателен".
|
||||||
|
2. Если да — напиши тест в том же коммите, без запроса подтверждения.
|
||||||
|
3. Если нет — не пиши тест, не упоминай его отсутствие.
|
||||||
|
4. При удалении функциональности — удали соответствующие тесты.
|
||||||
|
5. При обнаружении закомментированных или сломанных тестов — удали или почини.
|
||||||
Reference in New Issue
Block a user