GH GambleHub

Стратегія тестування ядра

1) Принципи

Пірамідально-трофейний баланс. База - швидкі модульні та контрактні тести; вище - компонентні та інтеграційні; на вершині - мінімальний, але цінний шар e2e.
Shift-left. Чим раніше ловимо дефект (лінтер, статичний аналіз, property-based), тим дешевше.
Deterministic by design. Керуємо часом, мережею, рандомом і зовнішніми залежностями.
Економіка якості. Будь-який тест - це «страховка»: мета - мінімізувати сумарні витрати (дефекти + супровід тестів).
Ризик-орієнтованість. Покриття концентрується на бізнес-інваріантах і протоколах (контракти, ідемпотентність, консистентність).

2) Рівні тестування та зони відповідальності

2. 1 Unit (модульні)

Перевіряють чисту логіку без I/O.
Миємо тільки межі (порт/адаптер), використовуємо фабрики для даних.
Швидкі (≤50 -100 мс/тест), паралеляться.

2. 2 Contract (постачальник ↔ споживач)

Фіксують API-контракти (HTTP/gRPC/event) між сервісами.
Використовуємо consumer-driven підхід: контракти зберігаються в VCS, перевіряються в CI постачальника.
Зменшують крихкість інтеграційних e2e.

2. 3 Component (над модулем, з реальним сховищем)

Запускаємо частину сервісу з реальною БД/кешем в контейнері (Testcontainers).
Валідуємо міграції схем, індекси, транзакції, блокування.

2. 4 Integration/System (наскрізні шляхи між сервісами)

Піднімаємо набір сервісів в ізольованому середовищі.
Перевіряємо наскрізні інваріанти: транзакційність, ретраї, ідемпотентність, обробку помилок.

2. 5 E2E (мінімальний «цінний» шар)

Реальні протоколи і оточення «як у проді», але обмежений сценарний набір: оплата → підтвердження → проводка; реєстрація → верифікація → вхід.
Використовуємо для випуску релізів і регресу високоризикових фіч.

3) Тестопридатна архітектура

Порти/адаптери (Hexagonal). Бізнес-ядро не знає про HTTP/SQL; залежності впроваджуються через інтерфейси.
Ін'єкція часу/рандома.'Clock','Random'- залежності; в тестах фіксуємо.
Конфігурована I/O абстракція. Черги, БД, KMS - через інтерфейси з тестовими реалізаціями.
Функціональні інваріанти. Явно формулюємо постумови і предикати - їх простіше тестувати і моніторити.

4) Дані для тестів

Фабрики/білдери замість статичних JSON-фікстур: менше крихкості.
Ідемпотентні сиди і reset-хук БД перед тестом (migrations → truncate → seed).
Каталоги кейсів: «норми», «краї», «помилки», «хаос».
Синтетика замість реальних ПД: генератори, маскування, профілі приватності.

5) Конкуренція та ідемпотентність

Тести на гонки (race): конкурентні записи/резерви/блокування.
Перевірка ідемпотентних ключів (наприклад,'( operation, external_id)'): повторні виклики не змінюють стан.
Ретраї і таймаути: гарантуємо коректність при тимчасових помилках.

Псевдокод (ідемпотентність):

dedupe_key = hash(op + external_id)
if exists(executions, dedupe_key): return previous_result else:
reserve(dedupe_key)
result = do_operation()
store(executions, dedupe_key, result)
return result

6) Час, таймаути, часові пояси

Всі збережені часи - UTC; в тестах використовуємо'FixedClock'.
Тестуємо DST-кейси (дублі/пропуски годинників), вікна «локального дня».
Таймаути перевіряємо монотонічними годинниками; симулюємо NTP-тремтіння.

7) Стійкість і хаос

Fault-injection: мережеві помилки, 5xx, затримки, часткова деградація (кеш недоступний).
Chaos-тести в середовищі pre-prod: відключення вузлів, перевантаження черг, розриви BGP/Anycast (емуляція).
Fallback-політики і деградація UX: тести повинні підтверджувати коректний «graceful degradation».

8) Продуктивність

Мікро-бенчмарки для критичних алгоритмів (з фіксацією CPU/alloc).
Навантажувальні профілі: baseline (p50/p95), стрес (пік), продовжені (soak) для витоків пам'яті.
Регрес-гейти: build провалюється, якщо p95 латентності гірше baseline> X%.

9) Безпека та відповідність

SAST/Lint: пошук вразливостей/антипатернів.
DAST/IAST: базові сценарії на стенді (XSS/SQLi/SSRF-проби).
Secrets-scan: відсутність ключів/паролів в коді та артефактах.
Privacy-тести: відсутність ПД в логах/трасуваннях, дотримання «управління згодою», профілі анонімізації для вивантажень.

10) Метрики якості та SLO

Test pass rate і flaky index (кількість нестабільних тестів/тиждень).

Coverage-цільове:
  • 90-100% для критичних модулів ядра,
  • 70-80% для периферії (з фокусом на інваріанти).
  • Release risk score: сукупність: зміни в критичних файлах × падіння бенчмарків × нові flaky.
  • Помилковий бюджет: зв'язка прод-SLO (аптайм/помилки) з експериментами і частотою релізів.

11) CI/CD і гейти

Матриця стадій:

1. Lint/Format/TypeCheck

2. Unit + Property-based

3. Contract provider/consumer

4. Component (Testcontainers)

5. Integration + Perf smoke

6. Security (SAST/Secrets)

7. Build/Package + SBOM

8. Deploy to pre-prod + e2e + chaos smoke

Гейти: стоп по падінню контрактів, зростанню латентності, новим критичним вразливостям.

Кеш і шардинг: прискорюємо pipeline за рахунок паралелізму та інкрементальних прогонів (за зміненими модулями).

12) Flaky-тести: виявлення та лікування

Автоповтор + кворум (2/3 прогонів).
Детектор флаки-патернів: залежність від часу/рандома/неявних очікувань.
Карантин з SLA: тест не блокує релізи, але зобов'язаний бути виправлений/переписаний в N днів.
Нульова толерантність до флаки в «ядрі» критичного шляху.

13) Property-based, мутаційне та фазз-тестування

Property-based: формулюємо властивості (комутативність, ідемпотентність, монотонність), генератори граничних даних.
Mutation testing: вимірюємо «силу» тестів (чи вбивають вони внесені мутації).
Fuzzing: протоколи/парсери/формати (JSON, Protobuf, CSV), особливо на кордонах безпеки.

Приклад властивості (псевдокод):

prop "serialize/deserialize roundtrip":
forAll(randomModel()):
decode(encode(model)) == model

14) Спостережуваність і зв'язок з тестами

Трасування тестів (trace-id в логах): зручно реплеїти в pre-prod.
Снапшоти метрик при перформанс-прогоні - зберігаємо як артефакт.
Контроль логів: відсутність чутливих полів, розмір логів в межах SLO.

15) Документація та процедури

Test Handbook: де які тести запускати, як писати фабрики, як оновлювати контракти.
Runbooks: реплей інциденту, швидка діагностика, відкат релізу.
Каталог інваріантів: список системних гарантій і посилань на відповідні тести/алерти.

16) Чек-лист архітектора

1. Описані інваріанти ядра і критичні шляхи?
2. Є матриця рівнів тестів і їх SLO (час, стабільність)?
3. Контракти версіонуються і валідуються в CI у постачальника і споживача?
4. Час/рандом/мережа контрольовані в тестах (FixedClock, Fault-injector)?
5. Налаштовані Testcontainers/ізольована БД, міграції перевіряються?
6. Є перформанс-базлайни і гейт на регресію?
7. Включені SAST/Secrets-scan і privacy-перевірки логів?
8. Ведеться облік flaky і є SLA на виправлення?
9. Зв'язок тестів з прод-SLO і помилковим бюджетом прозоро оформлена?
10. Документовані runbook'і і каталог інваріантів?

Висновок

Стратегія тестування ядра - це не список інструментів, а архітектурна здатність: тестопридатний дизайн, сувора ієрархія рівнів, керовані дані, відмовостійкість і метрики, вбудовані в CI/CD. Слідуючи описаним практикам, команда отримує швидкий і надійний зворотний зв'язок, а релізи стають передбачуваними і безпечними.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.