Тестирование приложений

Как, чем и зачем:)

Плавное погружение в тестирование

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

По мере роста приложения возникает необходимость в тестировании. Конечно, желательно строить процесс разработки таким образом, чтобы тестирование предшествовало выходу релизов, а не последние выступали в роли тестовой платформы(sic бывает очень часто:)). Сразу оговорюсь, речь идет об автоматическом тестировании на основе планов, а не о так называемом UAT – User Acceptance Testing. Это отдельная тема разговора, такое тестирование проводят люди с железными нервами, которым, как я слышал, в одной из отечественных контор даже разрешается пить пиво на работе.

Автоматические тесты предназначены более для выявления дефектов в запросах, поиска просчетов в алгоритмах(бейте граничными значениями по входам – узнаете много нового о своих функциях), нахождении мелких неточностей и упущений. Что представляет собой тест? Это последовательность действий, которая включает в себя проверку загрузки модулей в память, их инициализацию и выполнение некоторых действий с последующим сравнением результатов. Теоретически, подобными тестами можно покрыть все приложение, однако делать это смысла нет, так как даже тотальное авто-тестирование не дает 100% гарантии, что приложение и в жизни будет работать столь же успешно, как и на тестах.

Как мне кажется, одно из основных предназначений тестирования состоит в том, что дает возможность разработчику проверить, а будет ли работать данный метода/класс после внесения некоторых изменений и как эти изменения повлияют на работу других частей приложения, которые используют модифицированный код. Буду судить по себе – я достаточно часто возвращаюсь к уже написанным модулям, когда меня посещает очередная ИДЕЯ. Мне нравится делать рефакторинг уже созданного кода, но далеко не всегда изменения носят сугубо косметический характер и потом превращаются в головную боль. Когда же тесты готовы заранее, можно относительно безопасно работать с кодом. Так что – тесты поощряют разработчика заниматься рефакторингом.

Еще одним полезным моментом является то, что тестировать лучше маленькие порции кода, что уже подразумевает наличие хотя бы какого-то дизайна у приложения:)

Итак, с чего начать? Как же проводить тестирование? Как ни странно, начинается все с бумаги. Перед тем, как что-либо писать, нужно разработать тестовый план. Если необходимо тестировать бизнес-логику – не слезайте с заказчика, пока он не предоставит его, в случае же низкоуровневого взаимодействия полагайтесь только на свою фантазию, будьте максимально пессимистичны относительно входных данных, что почти соответствует тому, что придет в приложение, когда за дело возьмутся реальные пользователи. Давайте представим модуль который подлежит тестированию, как черный ящик, своего рода передаточную функцию, у которой есть входные и выходные сигналы. Хороший тестовый план должен включать в себя описание входных параметров и соответствующих им выходных значений. Так же неплохо включать в тестовый план ошибочные данные, чтобы проверить работу функции в таких вот ситуациях.

Наконец, план разработан, был выписан набор параметров и просчитаны выходные значения. Давайте подумаем, каким образом данные будут попадать на вход тестируемой функции. Хорошим тоном будет загружать тестовый сценарий из файла, нежели жестко кодировать граничные условия. Таким образом тест получается более гибкий и адаптируемый. Думаю, у каждого есть свои собственные излюбленные методы загрузки данных. Лично мне очень понравилось использовать для этого YAML(мы вернемся к этой теме чуть позже), ввиду простоты и формата файла, который можно редактировать вручную.

Идем дальше. Предположим, приложение активно использует какой-то источник данных. Довольно часто в его роли выступает СУБД. В принципе, можно сделать копию реальной рабочей базы с продакшн-сервера и гонять на ней тесты, но этот вариант имеет ряд недостатков. Во-первых, нет детерминированности данных – вы не знаете достоверно, что сейчас находится в таблице/таблицах. Во-вторых, тесты могут менять данные, так что в следующий раз придется иметь дело не только с настоящими данными, но и с синтетическими, попавшими туда в результате тестов(которые, кстати, не все могут закончиться успешно). Как мне кажется, достаточно удобно иметь заранее подготовленный дамп тестовой базы данных, который можно загружать в начале процедуры. Такой дамп можно сделать из реальной базы, удалив 80% информации, оставив лишь пару-тройку записей. Так же неплохо иметь описание этих данных – сколько и что содержится в таблицах, так что если запрос с INNER JOIN вернет 10 строк вместо содержащихся 2 в таблице – это повод серьезно призадуматься.

Подведем краткий итог. Для проведения тестирования нужно:

 

  1. подробный план, описывающий максимальное количество ситуаций
  2. удобный механизм доставки тестовых данных

To be continue