Модуль 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.
Безпечна практика модуля 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.
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 модуля
- Запустити
python -m unittest discover -s tests -v. - Повторити suite двічі й переконатися в exact однаковому результаті.
- Імпортувати CLI module та перевірити stdout=0.
- Запустити CLI success і failure через subprocess.
- Перевірити 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.
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.