QueryPort

Зелёный набор тестов ничего не обещает

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

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

Call to undefined method ProbeLogic::вСуточномПотолке()

В коде остался вызов метода, который я сам же и удалил. Он стоял не в вырезанном куске, а ниже по файлу, между проверкой длины входа и кэшем. Ошибка простая. А вот то, что её не заметили двести девяносто восемь проверок, простым не является.

Почему набор молчал

Я посмотрел, что именно проверяли те двести девяносто восемь на этой ручке. Четыре проверки: отбивается ли запрос методом GET, отбивается ли без токена, отбивается ли с чужой страницы, отбивается ли слишком длинный вход. Все четыре про отказ.

Ни одна не шла дальше. Дальше начинается обращение к модели, а у нас правило: в тестах модель не вызываем, это деньги и это медленно. Правило верное. Следствие из него было моей ошибкой: удачный путь ручки, которая приносит деньги, не проверял никто. Отказы покрыты вчетвером, успех ноль раз.

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

Считать надо пути, а не тесты

Полезный вопрос звучит не «сколько у нас тестов», а «какие пути проверены хотя бы однажды». У почти любой ручки, которая куда-то ходит, путей четыре класса:

  1. Отказ на входе. Не тот метод, нет токена, чужой источник, слишком длинный вход. Пишется первым, потому что дешевле всего.
  2. Отказ снаружи. Внешняя служба ответила ошибкой, ответила пустым телом, не ответила вовсе. Проверяется подстановкой ответа.
  3. Успех. Тот самый путь, ради которого ручка существует. Разбор ответа, сборка того, что увидит человек, запись расхода.
  4. Повтор. Второй такой же запрос. Здесь живёт кэш, и здесь же живут самые тихие дефекты: отдали ответ прошлого раза вместе с его замером.

У меня были покрыты первый класс целиком и ничего больше. Причём второй и третий закрываются не сложнее первого: внешнюю службу подменяем заготовленным ответом, а состояние вроде счётчика расхода уводим в песочницу через переменную окружения. Второе, кстати, оказалось не просто удобством. Пока счёт писался в живую папку сайта, проверить суточный потолок было НЕЛЬЗЯ вообще, а потолок это защита кошелька. Непроверяемая защита существует со слов автора, и всё.

Что я поменял в привычке

Первое. Правило «готово» теперь означает проверено выкатом. Не «набор зелёный», а один живой запрос к боевой ручке своими руками. У меня это заняло минуту и нашло дефект, который набор не видел вовсе.

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

Третье, и самое полезное. Каждую новую проверку я ломаю нарочно: вношу дефект, который она обязана поймать, и смотрю, покраснела ли она. В тот же день это спасло меня второй раз: подстава прошла молча, я полез разбираться и нашёл дыру не в коде, а в самой проверке, она отбрасывала пустые значения раньше сравнения.

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

Карта путей вашей ручки

Отметьте классы, проверенные хотя бы одним тестом. Считает браузер, отмеченное никуда не уходит. Процента здесь нет намеренно: он и создаёт ту самую иллюзию.

Дмитрий Подстригаев

Дмитрий Подстригаев

Разработчик, архитектор шлюза

Шестнадцать лет разработки, свой парк сайтов и свой шлюз к моделям. Пишу только о том, за что заплатил. Другие записи.

Читать дальше

Не согласны? Напишите. Содержательное возражение я публикую рядом с записью, а не прячу. А если у вас есть ручка, про которую непонятно, что у неё проверено, это и есть первый разговор на аудите.

Возразить или рассказать свою задачу · Разборы с инструментами