Услуги
Сайты и магазиныЛендинги ★Создание сайтовИнтернет-магазины
ИИ и автоматизацияИИ-секретарь ★Автоворонка и прогрев ★Telegram-боты ★Автоматизация ★CRM-разработка
ПродвижениеSEO-продвижениеAI-продвижение ★Контекстная рекламаSMM и соцсети
Наружка, печать и производствоВывески и буквыНаружная рекламаБаннеры и штендерыТипографияВизиткиШирокоформатБрендированиеОклейка автоТорговое оборудованиеМатериалы для рекламы
Дизайн и поддержкаДизайнПоддержка
КомплексDigital под ключ ★
РешенияКейсыПортфолиоЦеныО студииБлогКонтакты Обсудить проект

Что сработало

Инвариант, который нельзя записать в языке, записывается тестом

Правило Эванса короче любого регламента: утверждение, которое нельзя выразить средствами языка, записывается автотестом. Разбираем, как тестировать сервер, который нельзя останавливать, и почему свойства функции проверяются надёжнее, чем сценарии.

Замер: 9 августа 2026разбор своих ошибок

Чем проверено: 15 проверок API прогнаны через настоящий локальный сервер на временном зеркале, боевые данные не участвуют; 7 тестов свойств слияния и функциональный тест атомарной записи прогнаны, все зелёные

Короткий вывод. У API админки, через который проходят заявки и деньги, не было ни одного автотеста. Проверки страниц, ритуал перепроверки результата, состязательный разбор чужого вывода — всё построено, а середина пирамиды пустовала: код с деньгами ловил свои провалы в проде и человеком. Дыра закрыта: 15 проверок через настоящий локальный сервер на временном зеркале, боевые данные не трогаются, 15 из 15 зелёные. Тем же приёмом закрыт второй пункт — слияние сведено к чистой функции и обложено 7 тестами свойств. Правило Эванса: утверждение, которое нельзя выразить средствами языка, записывается автотестом.

Пирамида была, середина пустая

Главы о тестировании у Ричардсона мы читали, ожидая приговора «у вас ничего нет», и получили другое. Пирамида на месте, просто выглядит непривычно: проверки отдельных страниц — нижний слой, ритуал приёмки задачи по источнику истины — средний, состязательная перепроверка вывода второй моделью — верхний.

Провал обнаружился в одном месте, зато самом дорогом. Серверная часть, через которую идут заявки, счета и правки базы, не покрывалась ничем: ни одного автоматического сценария, проверка синтаксиса перед коммитом — и всё. Дефект виден по последствиям: один запрос уже обнулял базу заявок, и обнаружил это человек.

Почему тестов не было — объяснение честное, а не оправдательное. Боевой сервер трогать страшно, а тест без сервера бессмыслен: проверять надо не функцию, а поведение связки при конкурентных запросах и мусоре на входе. Отсутствие ответа на «как» тихо превращалось в отсутствие тестов вообще.

Как тестировать то, что нельзя останавливать

Решение оказалось дешевле страха. Тест поднимает настоящий локальный сервер на временном зеркале серверной части, авторизация идёт штатным механизмом, а не заглушкой, боевые данные не участвуют вовсе. Полный прогон занимает секунды и встаёт в тот же гейт, где раньше стояла одна проверка синтаксиса. Проверяются не «функции», а те способы сломать систему, которые уже случались или очевидно случатся.

Что проверяет тестКакой инцидент за этим стоит
Отказ без входадоступ к данным мимо авторизации
Конфликт версий при одновременной правкедве сессии пишут разом и затирают друг друга
Запрет обнуления: пустое поверх непустого не проходитзапрос, обнуливший базу заявок
Частичное сохранение не теряет соседние разделыправка одного раздела уносила остальные
Мусор на входе не даёт внутренней ошибкиневалидное тело запроса роняло обработчик
Первичное заполнение из образцапустая база после переустановки
После работы не остаётся временных файловмусор от прерванной записи копился рядом
Резервная копия на местеоткатываться было не к чему
Итог прогона15 из 15 зелёных

Соседний пункт того же дня закрывался по такому же принципу. Восемь оставшихся точек записи перевели на общий помощник атомарной записи, и подтверждением служил не факт правки, а два прогона: синтаксическая проверка по всем восьми файлам и функциональный тест помощника — испорченный на входе текст не должен затирать существующий реестр.

Свойства вместо примеров

Второй закрытый пункт интереснее первого, потому что тестируется там не сценарий, а математика. Инструмент слияния сводит правки нескольких сессий, и лекция про типы данных, устойчивые к слиянию, задаёт функции три обязательных свойства: результат не зависит от порядка аргументов, не зависит от группировки и не меняется при повторном применении.

Ценность формулировки в том, что все три проверяются напрямую, без придумывания примеров: слияние двух копий в одном порядке равно слиянию в обратном, слияние копии с самой собой возвращает её же. Дальше добавились свойства из предметной области.

  1. Без потерь — ни одна задача из обеих копий не исчезает.
  2. Идемпотентность — повторное слияние ничего не меняет.
  3. Симметрия — «своя» и «чужая» копия равноправны.
  4. Удаления не применяются — стирание в одной копии не выносит запись из результата.
  5. Без дублей — один идентификатор остаётся одной записью.
  6. Политика победителя — при равенстве прочего выигрывает оговорённая сторона.

Предварительным условием стал рефакторинг: логику слияния вынесли из скрипта в чистую функцию — без чтения файлов, без записи, без побочных эффектов. Её можно вызвать семь раз с разными аргументами, а скрипт, который сам ищет файлы и сам их перезаписывает, пришлось бы проверять запуском на живых данных — потому его обычно не проверяют вовсе. Итог — 7 тестов, все зелёные.

Правило, которое это обобщает

Формулировка из справочника паттернов короче любого нашего регламента: если утверждение об инварианте нельзя выразить средствами языка, пишите на него автоматический тест. Смысл не в тестах как таковых, а в переводе договорённостей из разряда «все же понимают» в разряд проверяемого.

Договорённостей такого рода накопилось много, и почти все живут в тексте. Сумма счёта равна сумме его строк. У рейса есть машина. Класс тарифа соответствует машине, а не весу груза. Ни одно из трёх утверждений нельзя выразить структурой файла, где всё это просто поля, — значит, по правилу Эванса каждое обязано существовать как проверка.

Что уже работает. Часть инвариантов проверяет валидатор расчётов по долгам — он же и находил расхождения раньше человека. Приём подтверждён на практике: инвариант, оформленный как проверка, ловит ошибку в момент внесения, а не через месяц на сверке.

Чего у нас всё ещё нет

  • Автопроверки общего ядра на каждом шаге. Справочник требует для общей части модели постоянной интеграции — частого сведения и автотестов, ловящих расхождение. У нас проверка включается при конфликте слияния: расхождение обнаруживается позже, чем возникло.
  • Полного пакета инвариантов. Три утверждения выше проверяются частично, сплошного набора нет.
  • Схемы данных. Единственная незакрытая дыра из семи по итогам разбора; описание структуры, версия формата и проверка при записи разобраны отдельным материалом.
Мера, по которой мы теперь считаем дыру закрытой. Не «код написан» и не «правило записано», а «есть проверка, которая краснеет, если это сломать, и она прогнана». По такой мере из семи дыр разбора закрыто пять, одна в работе и одна открыта — и последняя строка нам нравится больше, чем круглый отчёт.

Источники материала

  • Внутренний разбор пяти профильных книг от 31 июля 2026: дыра «ноль автотестов у API с деньгами» и отчёт о закрытии — состав 15 проверок, способ прогона, результат.
  • Крис Ричардсон, «Microservices Patterns», главы о пирамиде тестирования и контрактных тестах; Эрик Эванс, справочник паттернов — инварианты и интеграция общей части модели.
  • Авторский конспект курса «Distributed Systems»: три обязательных свойства функции слияния и вывод об их прямой проверяемости.
  • Отчёт о закрытии пунктов того же дня: рефакторинг слияния в чистую функцию, 7 тестов свойств, перевод восьми точек записи на общий помощник с двумя видами подтверждения.

В курсе — что считать доказательством работоспособности

Мера закрытия задачи: не «код написан» и не «правило записано», а «есть проверка, которая краснеет при поломке, и она прогнана». Разбираем, как превратить договорённость в проверку.

Программа курса и цены
Соседние материалы
Предыдущий замер: Что входит в две недели разбора — по днямСледующий замер: Половина книг — не про насВсе материалы журнала

Обсудим ваш проект

Оставьте заявку — свяжемся в течение 15 минут в рабочее время, зададим пару вопросов и пришлём ориентир по цене и срокам. Бесплатно, без обязательств.

  1. 1. Заявка или квиз
  2. 2. Короткий созвон / переписка
  3. 3. Бесплатная смета и план
  4. 4. Договор и старт

Бесплатно и ни к чему не обязывает. Ответим за 15 минут.