Что такое тестирование

Каждая новая задача затрагивает код сразу нескольких файлов. С ростом сложности проекта любое изменение начнёт порождать волны правок в функциях, шаблонах, потребует создания файлов миграции и других изменений в проекте. Самый непреодолимый предел, с которым сталкивается программист — это предел возможностей его памяти и внимания.
В прошлом спринте вы делали форму по обмену дисками. В форме были поля «Исполнитель» и «Название альбома», но не было поля «Год выпуска». Представьте себе, что перед сдачей проекта коллекционер просит вас добавить это поле. Вот какие фрагменты кода придётся исправить:
  • Объект формы, в котором нет необходимого поля;
  • View-функцию index, которая вызывает функцию send_msg;
  • Определение самой функции send_msg(): ей надо будет передавать дополнительный параметр date;
  • Шаблон текста письма: в него надо добавить новое поле;
  • Возможно, изменений потребует и шаблон формы в файле index.html;
  • А если бы данные из формы сохранялись в базу, то пришлось бы править модель и делать миграцию.
И всё это надо помнить и исправлять в крошечном проекте с одной-единственной формой!
Чем больше проект, тем сложнее вносить изменения. А если над проектом трудится коллектив, то программист вполне может и не знать, что его код использует кто-то ещё; небольшое исправление приведет к тому, что часть проекта просто перестанет работать.

Виды тестирования

Вокруг проверки качества проектов возникла огромная инфраструктура и отдельная культура. Вы слышали о тестировщиках и, возможно, сами занимались тестированием. Тестировщики пытаются проиграть все возможные сценарии и найти ошибки в работе проекта. Ручная проверка называется мануальное тестирование. Есть особая культура мануального тестирования: иногда тестировщик просто эмулирует поведение пользователя, но чаще у него есть конкретные сценарии, которые он реализует в интерфейсе проекта. Простейший сценарий тестирования формы входа на сайт:
  • Пользователь вводит правильный логин и пароль и входит на сайт;
  • Пользователь вводит неправильный логин и пароль, получает отказ и видит приглашение восстановить пароль;
  • Пользователь вводит правильный email в форму восстановления доступа и получает письмо со ссылкой на форму изменения пароля;
  • Пользователь вводит неправильный email в форму восстановления доступа и получает сообщение «такой email не найден».
Тестировщик проходит по таким сценариям и проверяет работу системы. По мере развития в проекте появляются всё новые и новые сценарии. Прежде чем сдать свою работу, программист обращается к тестировщику для проверки сценариев и функциональности.
После внесения изменений проводят и регрессионное тестирование — проверку уже работающих частей системы на ошибки, которые могли появиться в связи с добавлением новой функциональности.
Изменение одной части проекта может вызвать ошибки («регрессии») в другой части. Например, если различные view-функции отправляют сообщения через функцию send_msg(), а программист изменит её, это может привести к тому, что часть view-функций перестанет работать.
Мануальное тестирование — это долго и утомительно, и эту работу автоматизировали. Автоматическое тестирование может работать на разном уровне: эмулировать вызов функций и методов или даже имитировать работу пользователя.
В этом спринте тесты будут проверять работу нашего кода. Продолжая наш пример, можно написать программу, которая протестирует функцию send_msg(). А можно написать тест, который будет проверять работу view-функции.
Тесты для небольших частей кода называются юнит-тестами, а тесты, проверяющие работу внешних программных интерфейсов — это интеграционные тесты (они обеспечивают интеграцию между разными системами). Те и другие — функциональные тесты, поскольку испытывают они функциональность систем. Интеграционные тесты проверяют реальные задачи, например, может ли пользователь добавить запись на сайт. Юнит-тест проверяет работу участков кода, например — правильно ли функция обрабатывает входящие параметры.
Есть много иных видов тестирования. Можно тестировать производительность или предельную нагрузку на систему. А можно проверять систему на эстетическую красоту или удобство работы пользователей с интерфейсами. Есть даже тестирование, проверяющее объем выбросов CO₂ на единицу операции.

Когда надо писать тесты

Написание тестов — это большая часть работы программистов. Иногда даже вначале пишутся тесты, а только потом пишется код, соответствующий этим тестам. Эта практика называется Test Driven Development (TDD).
Соотношение числа протестированных строк кода к общему количеству значимых строк называется процентом покрытия тестами. Есть специальные утилиты, позволяющие отследить, была ли задействована конкретная строка (или её часть) во время запуска тестов.
Идеальное (и часто практически недостижимое) покрытие кода — стопроцентное, когда написаны тесты для всех позитивных и негативных исходов, для каждой функции и каждого из состояний классов и объектов, которые они могут порождать. А это значит, что объём тестов может превышать объём кода проекта!
Традиционно принимается на веру, что покрытый тестами код содержит меньше ошибок и доставит меньше проблем при внесении изменений. При этом так же принимается, что покрытый тестами код всё равно может содержать ошибки. Реальность такова, что требования к одному и тому же коду могут меняться, так же как может меняться среда и условия его выполнения.
Программисты очень часто сталкиваются с преодолением неучтённых ситуаций:
  • База данных прекрасно справляется с миллионами записей в таблице. Но если в таблицу добавляются миллионы записей в секунду, например, для подсчёта объёма потребленного трафика сотового оператора — возникнет ошибка.
  • Библиотека для обработки изображений, на 100% покрытая тестами, получит для обработки изображения со спутника с таким разрешением, о существовании которого создатели библиотеки даже не подозревали — и зависнет.
  • Генератор случайных чисел прекрасно справляется с симуляцией подбрасывания кубика в компьютерной игре — но оказывается предсказуем и приводит к деградации стойкости криптоалгоритмов.
Код пишут люди, а людям свойственно ошибаться. Мы часто считаем, что «всё сделали правильно» до тех пор, пока не отойдём на шаг от своей работы и не взглянем на неё свежим взглядом. Тесты помогают посмотреть на код со стороны.
Когда надо писать тесты и сколько их должно быть? Это вопрос одновременно и философский, и прагматичный.
Тесты — это тоже код, работа, которая стоит денег и времени. Помимо стоимости часа работы есть ещё цена времени для вывода продукта на рынок. Но не проверять и не тестировать свою работу — это значит постоянно сталкиваться с проблемами и исправлять ошибки в ходе эксплуатации, что всегда дороже. Ошибки могут привести к потере клиента или даже к закрытию бизнеса.
Если на проекта Yatube возникнет ошибка, не позволяющая пользователю зарегистрироваться, и при этом идёт реклама, приводящая на сайт новых клиентов, то все деньги рекламной компании будут потрачены впустую.
Поэтому давайте делать свою работу и разберёмся, как покрыть код проекта тестами!
Выберите правильный ответ:
3 из 3 правильно и 0 неправильно