Рассказ о том, как перестать откладывать на потом скучные, но важные вещи.

Контекст

Была у меня задача - проверять, является ли клиент крупным, или нет. Фактически, надо было, если определенная строка равна “крупный” (в любом регистре), то вернуть “Y”, иначе “N”, и записать это в базу, как bool.

Казалось бы, элементарщина.

Ну, я и набросал простую лямбду:

lambda x: "Y" if x.lower == "крупный" else "N",

Посмотрите в этот код десять секунд, всё же нормально?

Потому что, когда код попал в продакшн, начались странности. Все записи были промечены как “мелкие”, true нигде не проставлялось, хотя должно было. По итогу, я потратил несколько часов, разбираясь, откуда растут ноги, и, в итоге, заметил, что:

.lower — это я указываю на метод, а не вызываю его! 😥

Корректный код выглядел бы так:

lambda x: "Y" if x.lower() == "крупный" else "N",

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

Справедливости ради, конкретно тут львиная доля проблемы была в адово долгом feedback loop - это “проект выходного дня”, где используются очень скромные мощности, решение собирается в docker-образ и доставляется в закрытый контур через scp по каналу ограниченной пропускной способности.. Но это всё лирика, оправдания есть всегда.

Что меня спасло бы?

Достаточно было добавить несколько простейших тестов (хоть doctest):

>>> check_size("Крупный")
"Y"
>>> check_size("крупный")
"Y"
>>> check_size("иное")
"N"

Если бы я их написал сразу, то и ошибка всплыла бы мгновенно, а не после того, как эта лямбда уже была спрятана в глубинах логики, а автор стал рассчитывать на неё в production-окружении.

Я и раньше знал, что тесты — это полезно. Но как-то внутренне осознал и зауважал их ценность только после этого случая.

Даже на такую логику “в одну строчку”.

Подытожим

  • Глаз замыливается, опечатки неизбежны
  • Тесты экономят время - лучше потратить 5 минут на проверку, чем часы на дебаг
  • Shift left - если что-то сломается в будущем, вы сразу это заметите

Ссылки

Проконтролировать себя поможет CI/CD, куда можно встроить запрет выкатки без достаточного покрытия тестами:

  • coverage - модуль для проверки покрытия тестами
  • codeclimate - сервис с бесплатным тиром, который легко подключить для pet-проекта