От модульного теста до юзабилити: шесть проверок ПО для бизнеса, которые касаются ваших доходов
Любой, кто платит за разработку программного обеспечения, рано или поздно сталкивается с необходимостью оценить, насколько продукт готов к использованию. Подрядчик присылает отчёт, в котором перечислены проведённые проверки, и предлагает переходить к следующему этапу, а у человека по ту сторону договора остаётся ощущение, что за словами «всё протестировано» скрывается что-то важное, но непонятное.
Тестирование – одна из тех областей разработки, где профессиональный язык плохо переводится на язык бизнеса, и тому, кто финансирует проект, приходится либо доверять исполнителю безоговорочно, либо разбираться в деталях самостоятельно.
Тестирование нужно не для того, чтобы формально закрыть этап и подписать акт. Его смысл в другом: убедиться, что программа делает то, что было обещано, и не делает того, чего от неё не ждут. Первое кажется очевидным, но на практике именно здесь возникает больше всего расхождений, потому что обещанное в требованиях и обещанное в голове у человека, который эти требования формулировал, – не всегда одно и то же.
Второе же часто остаётся без внимания вовсе: никто не ожидает, что система потеряет данные при обновлении страницы или откажется работать на планшете, но именно такие неожиданности сильнее всего бьют по репутации и бюджету после запуска.
Возникает закономерный вопрос: почему для одной программы нужно столько разных проверок, почему нельзя придумать одну универсальную и закрыть вопрос раз и навсегда. Ответ связан с тем, что программный продукт устроен сложнее, чем кажется со стороны.
У него есть отдельные детали, есть связи между этими деталями, есть поведение всей системы целиком, есть условия, в которых она работает, и есть люди, которые ею пользуются. Каждый из этих уровней может дать сбой независимо от остальных, и проверка, хорошо работающая на одном уровне, почти ничего не говорит о другом. Именно поэтому тестирование распадается на виды, и каждый вид отвечает на свой вопрос.
Понимать эту разницу важно не меньше, чем разбираться в договоре, потому что именно от человека, финансирующего проект, зависит, на что выделить бюджет, а на что можно не тратить, и именно он в итоге отвечает за то, как продукт встретят те, для кого он создавался.
Когда есть представление о том, какие вопросы закрывает та или иная проверка, разговор с исполнителем перестаёт быть обменом формальными отчётами и становится обсуждением реальных рисков. Это не требует технических знаний, но требует понимания логики, по которой тестирование устроено именно так, а не иначе.
Мы разберём шесть самых распространённых видов тестирования – от проверки отдельных функций до имитации наплыва тысяч пользователей, – и в каждом случае посмотрим, на какой вопрос отвечает эта проверка, чем она помогает бизнесу и что стоит уточнить у исполнителя, чтобы картина была полной.
Отдельно поговорим о том, что изменилось за последний год: тестирование, как и вся разработка, не стоит на месте, и полезно знать, какие изменения стоит заметить в работе подрядчика, а какие можно спокойно пропустить, не углубляясь в технические детали.
Модульное тестирование
Модульное тестирование – это проверка самой маленькой части программы в изоляции от всего остального. Речь идёт об отдельной функции, одном расчёте, одной операции, которая должна работать сама по себе, независимо от того, подключена ли она к базе данных, вызывается ли из интерфейса или ждёт ответа от другого сервиса.
Разработчик пишет небольшой фрагмент кода, который подаёт на вход этой функции конкретные значения и смотрит, возвращает ли она ожидаемый результат. Если функция должна складывать два числа, тест проверяет, что при входных данных «два» и «три» на выходе получается «пять». Если функция должна отклонять неверный пароль, тест проверяет, что она действительно его отклоняет, а не пропускает.
Смысл такой проверки в том, чтобы поймать ошибку в момент её появления, а не тогда, когда она уже встроена в общую конструкцию. Когда разработчик пишет новую функцию, он может быть уверен в её логике настолько, насколько вообще можно быть уверенным в чём-то, что ещё не запускалось.
Модульный тест запускается мгновенно, работает изолированно и не требует ни базы данных, ни интерфейса, ни внешних сервисов. Это позволяет проверить функцию на десятках вариантов входа за секунды и убедиться, что она ведёт себя предсказуемо не только в обычном случае, но и на границах:
- пустое значение вместо ожидаемого числа или строки;
- отрицательное число там, где по смыслу допустимы только положительные;
- слишком длинная строка, превышающая разумный предел;
- отсутствие данных, когда функция ждёт обязательное значение;
- неверный формат, например буквы вместо цифр в числовом поле.
Ошибки, найденные на этом уровне, стоят дешевле всего: их исправление занимает минуты, а не дни, и они не успевают добраться до пользователя.
Проверить результаты модульного тестирования можно двумя способами. Первый – посмотреть на отчёт о запуске: сколько тестов было, сколько прошло, сколько упало и с какими сообщениями. Если тест упал, в отчёте обычно видно, какая именно функция и с какими входными данными дала сбой:
- общее число тестов и число успешно пройденных;
- список упавших тестов с указанием функции и входных данных;
- сообщения об ошибках, которые привели к падению;
- дата и версия кода, к которой относится отчёт.
Второй способ – посмотреть на покрытие кода: специальный инструмент показывает, какие строки программы были выполнены во время тестов, а какие остались нетронутыми. Если значительная часть кода не покрыта тестами, это значит, что там могут скрываться ошибки, о которых никто не узнает до запуска. Ориентиром для большинства команд считается покрытие около восьмидесяти процентов, хотя эта цифра не является универсальным стандартом и зависит от характера проекта.
Покрытие показывает не качество тестов, а лишь то, что код хотя бы раз был выполнен. Тест может формально покрыть строку, но не проверить её поведение как следует. Поэтому разумно смотреть не только на процент, но и на то, какие именно сценарии проверяются – особенно те, что связаны с деньгами, данными пользователей и критичными операциями.
Интеграционное тестирование
Интеграционное тестирование – это проверка того, как разные части программы взаимодействуют друг с другом. Если модульное тестирование смотрит на каждую функцию в одиночку, то интеграционное начинается там, где эти функции встречаются.
Один модуль передаёт данные другому, второй обращается к базе данных, третий ждёт ответа от внешнего сервиса – и на каждом из этих стыков что-то может пойти не так, даже если каждая часть по отдельности работала безупречно. Программа складывается из множества деталей, и гладкость их соединения – отдельная задача, которую нельзя решить проверкой самих деталей.
Суть в том, чтобы убедиться: части системы понимают друг друга одинаково. Один модуль может ожидать число, а получать строку, другой – отправлять дату в одном формате, тогда как третий готов принять только другой.
Бывает и так, что модуль корректно работает сам по себе, но при обращении к нему с определённой последовательностью запросов начинает вести себя непредсказуемо. Всё это не ошибки отдельных функций, а ошибки связей между ними, и искать их нужно именно на стыках.
Интеграционное тестирование как раз и проверяет эти переходы:
- формат данных, который один модуль отправляет, а другой принимает;
- совпадение ожиданий: что один модуль считает обязательным, а другой – необязательным;
- сохранность информации при передаче от одной части к другой;
- поведение системы, когда соседний модуль отвечает медленно или не отвечает совсем;
- корректность обработки ответа, пришедшего в неожиданном виде;
- порядок вызовов, если один модуль должен сработать строго после другого.
Программа редко живёт в изоляции: она обращается к платёжной системе, к службе уведомлений, к хранилищу файлов, к сторонним справочникам. Каждое такое обращение – тоже стык, и проверять его нужно отдельно, потому что внешний сервис может ответить медленнее, чем рассчитывали, вернуть ошибку вместо данных или изменить формат ответа после обновления на своей стороне.
Интеграционное тестирование включает и эти случаи: как система поведёт себя, если платёжная система не подтвердила операцию, если служба уведомлений временно недоступна, если справочник вернул пустой список вместо ожидаемого набора значений.
Проверить результаты интеграционного тестирования можно по отчёту, в котором фиксируются проверенные связки и их состояние. В отличие от модульных тестов, здесь важны не только «прошло» или «упало», но и то, какие именно стыки были охвачены проверкой, а какие остались в стороне:
- перечень проверенных связок между модулями;
- проверки обращений к внешним сервисам;
- описание сценариев, при которых соседний модуль отвечает медленно или с ошибкой;
- список стыков, которые не были охвачены проверкой, и причина, по которой их пропустили;
- сообщения о сбоях с указанием, на каком именно переходе между частями они возникли.
Интеграционные проверки сложнее автоматизировать, чем модульные: им нужны работающие базы данных, доступные внешние сервисы, согласованные тестовые наборы данных.
Поэтому в отчёте полезно видеть, какая часть этих проверок выполняется автоматически при каждом изменении, а какая проводится вручную и, следовательно, может отставать от текущего состояния кода. Если все интеграционные проверки ручные и проводятся только перед сдачей этапа, риск, что какой-то стык сломается между проверками, заметно выше.
Системное тестирование
Системное тестирование – это проверка готового продукта целиком, когда все части уже собраны вместе и работают как одна система. Если модульное тестирование смотрело на отдельные функции, а интеграционное – на стыки между ними, то системное начинается там, где важно, выполняет ли программа в целом то, что от неё требовалось.
Проверка идёт не по внутреннему устройству, а по внешнему поведению: система получает входные данные, выполняет операции и выдаёт результат, и этот результат сравнивается с тем, что записано в требованиях.
Суть в том, чтобы убедиться: продукт соответствует заявленным требованиям и ведёт себя предсказуемо в тех условиях, в которых его будут использовать. На этом уровне проверяются полные сценарии работы – не отдельные кнопки и не переходы между модулями, а законченные пути, которые проходят пользователи или которые описывают бизнес-процессы.
Система проверяется на соответствие функциональным требованиям, на корректность обработки ошибок и неверных данных, на поведение при нестандартных ситуациях. Здесь же выявляются расхождения между тем, что было записано в документации, и тем, как программа работает на самом деле:
- полные сценарии работы, описанные в требованиях, от начала до конца;
- соответствие поведения системы функциональным требованиям;
- корректность обработки ошибочных и неверных входных данных;
- поведение системы в нестандартных ситуациях, не предусмотренных обычным ходом работы;
- согласованность работы всех частей при выполнении общего сценария;
- отсутствие расхождений между документацией и фактическим поведением программы.
Отдельно стоит сказать о том, что системное тестирование проверяет не только «счастливый путь», важно посмотреть, как система ведёт себя, когда что-то идёт не так: пользователь ввёл неверные данные, обязательное поле осталось пустым, операция была прервана на середине, внешний сервис ответил ошибкой.
Именно в таких ситуациях проявляются слабые места, которые не видны при проверке нормального хода работы, и именно они чаще всего становятся источником проблем после запуска. Системное тестирование включает и эти случаи, потому что проверяет продукт таким, каким его встретят реальные условия.
Если в отчёте перечислены общие формулировки вроде «проверена работа системы», но нет привязки к конкретным требованиям, это повод уточнить, какие именно сценарии были прогнаны и что они подтверждают. Хороший отчёт показывает связь между требованием, сценарием проверки и результатом:
- перечень проверенных сценариев с привязкой к требованиям;
- отдельно – сценарии, проверяющие обработку ошибок и неверных данных;
- список требований, которые не были покрыты проверками, и причина, по которой их пропустили;
- описание нестандартных ситуаций, в которых проверялось поведение системы;
- сообщения о расхождениях между документацией и фактическим поведением программы;
- итоговое заключение о готовности системы к следующему этапу.
Системное тестирование проводится на собранной системе, близкой к той, которая пойдёт в работу, и это отличает его от проверок на уровне отдельных частей. Поэтому в отчёте полезно видеть, в каких условиях проводилась проверка: на какой версии сборки, с какими настройками, с какими данными. Если условия не описаны, сложно понять, насколько результаты отражают реальное поведение продукта, а не особенности конкретной тестовой среды.
Регрессионное тестирование
Регрессионное тестирование – это проверка того, что после внесённых изменений в программе продолжает работать всё то, что работало раньше. Любая правка, даже самая небольшая, затрагивает не только тот участок, ради которого она делалась.
Исправление одной функции может неожиданно повлиять на другую, добавление новой возможности – изменить поведение старой, обновление настроек – сказаться на работе смежных частей. Регрессионное тестирование как раз и нужно для того, чтобы поймать такие последствия до того, как они доберутся до пользователей.
Если после правки не прогнать проверки по уже работавшим сценариям, никто не узнает, что где-то по цепочке что-то сломалось, пока об этом не сообщит пользователь. Регрессионное тестирование возвращается к тем сценариям, которые уже были проверены раньше, и убеждается, что они по-прежнему проходят:
- сценарии, которые уже работали до внесения изменений;
- функции, смежные с той, которую правили;
- участки, которые связаны с изменённой частью через общие данные или общие настройки;
- поведение системы после обновления настроек или конфигурации;
- корректность работы после добавления новой возможности рядом со старой.
Отдельно стоит сказать о том, что регрессионное тестирование бывает разным по объёму. Полная регрессия прогоняет все накопленные проверки и даёт наиболее надёжную картину, но требует времени и ресурсов. Частичная регрессия ограничивается теми участками, которые с наибольшей вероятностью могли пострадать от конкретного изменения, и проводится быстрее, но оставляет больше пространства для неожиданностей.
Хороший отчёт показывает связь между внесённым изменением, затронутыми участками и прогнанными проверками, чтобы можно было оценить, насколько полно была охвачена зона риска:
- перечень проверок, прогнанных после изменения;
- связь между изменением и теми участками, которые оно могло затронуть;
- отдельно – проверки критичных участков: оплата, авторизация, работа с данными;
- список проверок, которые не были прогнаны, и причина, по которой их пропустили;
- сообщения о сбоях с указанием, какая именно проверка и какой участок дали сбой.
Регрессионное тестирование особенно выигрывает от автоматизации, потому что одни и те же проверки приходится прогонять после каждого изменения. Если все регрессионные проверки выполняются вручную, они неизбежно отстают от темпа правок: разработчик вносит изменения быстрее, чем тестировщик успевает пройти все сценарии заново.
Юзабилити-тестирование
Юзабилити-тестирование – это проверка того, насколько легко и понятно человеку работать с программой. Если предыдущие виды тестирования отвечали на вопрос, работает ли система и правильно ли она выполняет операции, то юзабилити-тестирование отвечает на другой вопрос: может ли обычный пользователь разобраться, что ему делать, и пройти нужный путь без лишних усилий.
Суть в том, что удобство – это не украшение и не вопрос вкуса, а такая же характеристика продукта, как правильность расчётов или скорость ответа. Если человеку приходится догадываться, куда нажать, чтобы продолжить, если он не понимает, что от него требуется в форме, если после действия он не видит, что произошло, – это не мелкие неудобства, а причины, по которым продукт не выполняет свою задачу.
Юзабилити-тестирование смотрит на программу глазами того, кто будет ею пользоваться, и проверяет, насколько логика интерфейса совпадает с логикой человека, который пришёл решить свою задачу:
- понятность интерфейса: ясно ли, что означает каждый элемент и куда ведёт каждое действие;
- логичность последовательности шагов: совпадает ли порядок действий в программе с тем, как человек представляет себе задачу;
- заметность важных элементов: видны ли кнопки, подсказки и сообщения там, где пользователь их ищет;
- понятность текстов: не вызывают ли подписи, сообщения об ошибках и подсказки вопросов и двусмысленностей;
- обратная связь: видит ли пользователь, что его действие сработало и что произошло дальше;
- восстановление после ошибки: понятно ли, что делать, если что-то пошло не так, и легко ли вернуться на нужный шаг.
В отличие от многих других видов тестирования, здесь важны не только действия, но и реакция человека на них. Участнику дают задачу – например, оформить заказ или найти нужный раздел – и смотрят, как он её выполняет: где задерживается, что пытается нажать, в какой момент обращается к подсказке, а в какой – сдаётся.
Ценность таких наблюдений в том, что они показывают реальные затруднения, а не предполагаемые. Разработчик, который писал интерфейс, знает, как всё устроено, и ему многое кажется очевидным; человек со стороны видит те же экраны впервые и ведёт себя иначе.
На что необходимо смотреть в отчёте о юзабилити-тестировании:
- перечень задач, которые предлагались участникам, и результаты их выполнения;
- конкретные экраны и шаги, на которых возникали затруднения;
- описание того, что именно вызывало затруднения: непонятная подпись, скрытая кнопка, неочевидная последовательность;
- случаи, когда участник не смог завершить задачу или завершил её с ошибкой;
- предложения по исправлению с указанием, какой именно элемент интерфейса нужно изменить.
Юзабилити-тестирование не требует большой выборки: значительная часть проблем обнаруживается уже на первых пяти-шести участниках, потому что люди натыкаются на одни и те же затруднения. Поэтому отсутствие в отчёте большого числа участников само по себе не говорит о том, что проверка была поверхностной.
Важнее другое – были ли среди участников те, кто соответствует целевой аудитории продукта, и проверялись ли те задачи, которые этой аудитории действительно нужно решать.
Нагрузочное тестирование
Нагрузочное тестирование – это проверка того, как система ведёт себя, когда на неё одновременно приходит много пользователей или много запросов. Сохранит ли система работоспособность и приемлемую скорость, когда нагрузка приблизится к реальной или превысит её.
База данных может не справиться с одновременными запросами, сервер может исчерпать память, очередь обработки может вырасти настолько, что время ответа станет неприемлемым. Нагрузочное тестирование имитирует поток пользователей или запросов и замеряет, как система реагирует:
- время отклика системы при разном количестве одновременных пользователей или запросов;
- поведение системы при нагрузке, приближенной к ожидаемой в реальной эксплуатации;
- поведение при пиковой нагрузке, которая может возникнуть в результате рекламы, сезонного всплеска или публикации в крупных источниках;
- устойчивость системы при длительной работе под нагрузкой: не накапливаются ли ошибки, не происходит ли постепенное замедление;
- корректность обработки ситуаций, когда нагрузка превышает возможности системы: не теряются ли данные, не нарушается ли целостность операций;
- способность системы восстановиться после снятия нагрузки и вернуться к нормальной работе.
Ценность представляет картина того, как меняется поведение системы с ростом нагрузки: где начинается замедление, при каком количестве пользователей появляются первые ошибки, какой запас прочности остаётся до того предела, за которым система перестаёт справляться. Если проверка показывает, что система стабильно работает при нагрузке вдвое больше ожидаемой, это даёт запас уверенности.
Хороший отчёт показывает зависимость времени отклика от количества пользователей или запросов, отмечает моменты появления ошибок и описывает, как система вела себя после снятия нагрузки:
- описание сценария нагрузки: какие действия имитировались, с какой интенсивностью, как долго;
- показатели времени отклика при разном уровне нагрузки, а не только среднее значение;
- момент, при котором начинают появляться ошибки или заметное замедление;
- поведение системы при пиковой нагрузке и после её снятия;
- проверка длительной работы под нагрузкой, если она проводилась;
- вывод о том, какой запас прочности есть у системы относительно ожидаемой нагрузки.
Последние тренды в тестировании программного обеспечения
- Умные инструменты сами выполняют проверки. Раньше они только помогали писать тесты, теперь всё чаще проходят сценарии от начала до конца без участия человека. Около 40% процессов разработки и тестирования уже частично переданы таким системам.
- Скрипты чинят себя сами. Если интерфейс изменился, проверка не падает, а подстраивается. Время на сопровождение сокращается более чем на 40%. Риск: может «починить» и ту проверку, которая должна была упасть, поэтому результат кто-то должен просматривать.
- Сценарии проверки создаются прямо из требований. Описание задачи на обычном языке превращается в готовые проверки. Больше половины применений умных инструментов в отечественных компаниях – именно это.
- Проверяют не только код, но и «умные» функции. Рекомендации, сортировка, разговорные помощники требуют отдельных проверок: ведёт ли модель себя предсказуемо в разных ситуациях.
- Среда проверки стала ближе к рабочей. Те же настройки, те же объёмы данных, те же внешние подключения – чтобы результаты не расходились с реальностью после запуска.
- Отчёты стали наглядными. Вместо таблиц с галочками – сводки: что покрыто, где пробелы, какие риски остаются.
Разработка ПО от 66 Бит
Тестирование – одна из самых загадочных тем в разработке ПО, но вы разобрались в ней всего за 10 минут. Самое время применить знания на практике, а если тестировать пока нечего, советуем обратиться в 66 Бит!
Наши опытные специалисты не только проведут глубокий аудит ваших бизнес-процессов и разработают эффективную систему, но и проведут тщательное тестирование необходимых компонентов, чтобы вы были уверены в качестве и производительности полученного ПО. Подробнее о нас читайте на нашем сайте по ссылке!