Модуль 7 · Урок 28 із 58

Integration tests: CLI, filesystem і deterministic suite

Unit tests швидко локалізують logic defects, але не доводять, що package imports, CLI arguments, filesystem encoding і adapters працюють разом. Невелика кількість integration tests закриває wiring без production data або реальних зовнішніх side effects.

integration testTemporaryDirectorysubprocessdeterminism

Безпечна практика модуля 7

Пакет містить лише synthetic fixtures, unittest, Mock/spec_set, TemporaryDirectory та локальний subprocess. Жодних персональних чи production-даних, secrets, мережевих викликів або зовнішніх залежностей.

Завантажити практичний пакет →

Integration test перевіряє межу між components

Він може викликати public service з real JSON adapter або запустити CLI як child process. Scope треба назвати: file adapter + parser + domain service, але без network; або full CLI з bundled synthetic fixture. «Integration» не означає автоматично production database.

Boundary: real code усередині scope, controlled substitute лише за scope boundary, deterministic synthetic input і cleanup після test.

TemporaryDirectory дає isolated filesystem

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    root = Path(directory)
    source = root / "input.json"
    target = root / "report.json"
    source.write_text('[{"id":"case-01"}]', encoding="utf-8")

    build_report(source, target)
    self.assertTrue(target.is_file())

High-level tempfile interfaces працюють як context managers і виконують cleanup. Test не залежить від Desktop path, existing file або permissions production uploads. Для Windows не тримайте file handle відкритим, якщо код має перейменувати чи видалити той самий path.

CLI contract включає process boundary

import subprocess
import sys

completed = subprocess.run(
    [sys.executable, "-m", "src.main", "--input", str(source)],
    cwd=project_root,
    capture_output=True,
    text=True,
    timeout=10,
    check=False,
)
self.assertEqual(completed.returncode, 0)
self.assertEqual(completed.stdout, "accepted=1\n")
self.assertEqual(completed.stderr, "")

Передавайте args sequence з shell=False, current interpreter через sys.executable, explicit timeout і captured streams. Success і expected failure мають різні exit codes; stable data output належить stdout, diagnosis — stderr.

Clock, randomness і environment — dependencies

Test, що очікує поточну дату, випадковий order або machine locale, є flaky. Передайте now/Random/configuration у service або patch controlled lookup. Фіксуйте seed лише коли саме pseudo-random sequence є частиною test; краще assert invariant, а не конкретний випадковий value.

service = ReportService(now=lambda: datetime(2026, 9, 4, tzinfo=UTC))
self.assertEqual(service.serial(), "REPORT-20260904")

Suite має кілька рівнів evidence

  • Багато fast unit tests для pure/domain logic.
  • Менше integration tests для file/database/API adapters.
  • Кілька end-to-end tests для critical user flow.

Це не фіксований percentage pyramid. Орієнтир — speed, failure localization і risk. Якщо вся suite mock-only, wiring defects невидимі; якщо все end-to-end, diagnosis повільна й fragile.

Coverage — карта виконання, а не quality score

100% line coverage може не перевірити boundaries, wrong outputs або missing side-effect rollback. Використовуйте coverage, щоб знаходити unexecuted risk areas, але review assertions, mutation resistance і production incidents окремо. Не додавайте беззмістовні tests лише заради числа.

Практичний quality gate модуля

  1. Запустити python -m unittest discover -s tests -v.
  2. Повторити suite двічі й переконатися в exact однаковому результаті.
  3. Імпортувати CLI module та перевірити stdout=0.
  4. Запустити CLI success і failure через subprocess.
  5. Перевірити cleanup temp files і відсутність secret markers.

Модуль 7 завершено

Після тесту прогрес становитиме 28/58 уроків. Проєкт 1 залишається доступним; проєкт 2 відкриється в наступному checkpoint після модуля 8. Final, PDF, QR та email-сертифікат лишаються заблокованими.

Definition of Done

  • Integration scope і excluded dependencies названі.
  • Filesystem tests ізольовані в temporary directory.
  • CLI перевірено як process: exit, stdout, stderr і timeout.
  • Time, randomness та environment контрольовані.
  • Suite швидка, repeatable і має evidence з unit та integration levels.

Методичні джерела

Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть лише на офіційну документацію Python.

Практична перевірка · урок 28 з 47

Закріпіть матеріал уроку

Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.

1. Коли integration test є потрібним доповненням до unit tests parser і service окремо?
2. Чому TemporaryDirectory кращий за hard-coded C:\Users\Author\Desktop для filesystem test?
3. Які чотири outcomes треба перевірити для CLI success process через subprocess.run?