Автоматизированное тестирование программного обеспечения - часть процесса тестирования на этапе контроля качества в процессе разработки программного обеспечения. Оно использует программные средства для выполнения тестов и проверки результатов выполнения, что помогает сократить время тестирования и упростить его процесс.
Первые попытки "автоматизации" появились в эпоху операционных систем DOS и CP/M. Тогда она заключалась в выдаче приложению команд через командную строку и анализе результатов. Чуть позднее добавились удаленные вызовы через API для работы по сети. Впервые об автоматизированном тестировании упоминается в книге Фредерика Брукса "Мифический человеко-месяц", где говорится о перспективах использования модульного тестирования. Но по-настоящему автоматизация тестирования стала развиваться только в 1980-х годах.
Существует два основных подхода к автоматизации тестирования: тестирование на уровне кода и тестирование пользовательского интерфейса (в частности, GUI-тестирование). К первому типу относится, в частности, модульное тестирование. Ко второму - имитация действий пользователя с помощью специальных тестовых фреймворков.автоматизация.
Наиболее распространенной формой автоматизации является тестирование приложений через графический пользовательский интерфейс (англ. GUI). Популярность такого вида тестирования объясняется двумя факторами: во-первых, приложение тестируется тем же способом, которым его будет использовать человек, во-вторых, можно тестировать приложение, не имея при этом доступа к исходному коду.автоматизация развивалась в течение 4 поколений инструментов и техник:
· утилиты записи и воспроизведения (англ. capture/playback tools) записывают действия тестировщика во время ручного тестирования. Они позволяют выполнять тесты без прямого участия человека в течение продолжительного времени, значительно увеличивая продуктивность и устраняя "тупое" повторение однообразных действий во время ручного тестирования. В то же время, любое малое изменение тестируемого ПО требует перезаписи ручных тестов. Поэтому это первое поколение инструментов не эффективно и не масштабируемо;
· написание сценария (англ. scripting) - форма программирования на языках, специально разработанных для автоматизации тестирования ПО - смягчает многие проблемы инструментов записи и воспроизведения. Но разработкой занимаются программисты высокого уровня, которые работают отдельно от тестировщиков, непосредственно запускающих тесты. К тому же скрипты более всего подходят для тестирования GUI и не могут быть внедренными, пакетными или вообще каким-либо образом объединены в систему. Наконец, изменения в тестируемом ПО требуют сложных изменений в соответствующих скриптах, и поддержка все возрастающей библиотеки тестирующих скриптов становится в конце концов непреодолимой задачей;
· управляемое данными тестирование (англ. Data-driven testing) - методология, которая используется в автоматизации тестирования. Особенностью является то, что тестовые скрипты выполняются и верифицируются на основе данных, которые хранятся в центральном хранилище данных или базе данных. Роль базы данных могут выполнять ODBC-ресурсы, csv или xls файлы и т. д. Управляемое данными тестирование - это объединение нескольких взаимодействующих тестовых скриптов и их источников данных в фреймворк, используемый в методологии. В этом фреймворке переменные используются как для входных значений, так и для выходных проверочных значений: в тестовом скрипте обычно закодированы навигация по приложению, чтение источников данных, ведение логов тестирования. Таким образом, логика, которая будет выполнена в скрипте, также зависит от данных;
· тестирование по ключевым словам (англ. Keyword-based) автоматизация подразумевает разделение процесса создания кейсов на 2 этапа: этап планирования и этап реализации. В этом случае конечный тест представляет собой не программный код, а описание последовательности действий с их параметрами (например, "завести в базе данных пользователя с логином XXX и паролем YYY"). При этом фреймворк отвечает за непосредственную реализацию ключевых слов (действий), а дизайнеру тестов достаточно иметь представление о всём наборе действий, реализованных во фреймворке. Это даёт возможность создавать тесты людям, не имеющим навыков программирования.
Одной из главных проблем автоматизированного тестирования является его трудоемкость: несмотря на то, что оно позволяет устранить часть рутинных операций и ускорить выполнение тестов, большие ресурсы могут тратиться на обновление самих тестов. Это относится к обоим видам автоматизации. При рефакторинге часто бывает необходимо обновить и модульные тесты, а изменение кода тестов может занять столько же времени, сколько и изменение основного кода. С другой стороны, при изменении интерфейса приложения необходимо заново переписать все тесты, которые связаны с обновленными окнами, что при большом количестве тестов может отнять значительные ресурсы.
Модульное тестирование, или юнит-тестирование (англ. unit testing) - процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.
Идея состоит в том, чтобы писать тесты для каждой нетривиальной функции или метода. Это позволяет достаточно быстро проверить, не привело ли очередное изменение кода к регрессии, то есть к появлению ошибок в уже оттестированных местах программы, а также облегчает обнаружение и устранение таких ошибок.
Цель модульного тестирования - изолировать отдельные части программы и показать, что по отдельности эти части работоспособны.
Этот тип тестирования обычно выполняется программистами.
Поощрение изменений.
Модульное тестирование позже позволяет программистам проводить рефакторинг, будучи уверенными, что модуль по-прежнему работает корректно (регрессионное тестирование). Это поощряет программистов к изменениям кода, поскольку достаточно легко проверить, что код работает и после изменений.
Упрощение интеграции.
Модульное тестирование помогает устранить сомнения по поводу отдельных модулей и может быть использовано для подхода к тестированию "снизу вверх": сначала тестируются отдельные части программы, затем программа в целом.
Документирование кода.
Модульные тесты можно рассматривать как "живой документ" для тестируемого класса. Клиенты, которые не знают, как использовать данный класс, могут использовать юнит-тест в качестве примера.
Отделение интерфейса от реализации.
Поскольку некоторые классы могут использовать другие классы, тестирование отдельного класса часто распространяется на связанные с ним. Например, класс пользуется базой данных; в ходе написания теста программист обнаруживает, что тесту приходится взаимодействовать с базой. Это ошибка, поскольку тест не должен выходить за границу класса. В результате разработчик абстрагируется от соединения с базой данных и реализует этот интерфейс, используя свой собственный mock-объект. Это приводит к менее связанному коду, минимизируя зависимости в системе.
Как и любая технология тестирования, модульное тестирование не позволяет отловить все ошибки программы. В самом деле, это следует из практической невозможности трассировки всех возможных путей выполнения программы, за исключением простейших случаев. Кроме того, происходит тестирование каждого из модулей по отдельности. Это означает, что ошибки интеграции, системного уровня, функций, исполняемых в нескольких модулях, не будут определены. Кроме того, данная технология бесполезна для проведения тестов на производительность. Таким образом, модульное тестирование более эффективно при использовании в сочетании с другими методиками тестирования.
Тестирование программного обеспечения - комбинаторная задача. Например, каждое возможное значение булевской переменной потребует двух тестов: один на вариант TRUE, другой - на вариант FALSE. В результате на каждую строку исходного кода потребуется 3-5 строк тестового кода.
Для получения выгоды от модульного тестирования требуется строго следовать технологии тестирования на всём протяжении процесса разработки программного обеспечения. Нужно хранить не только записи обо всех проведённых тестах, но и обо всех изменениях исходного кода во всех модулях. С этой целью следует использовать систему контроля версий ПО. Таким образом, если более поздняя версия ПО не проходит тест, который был успешно пройден ранее, будет несложным сверить варианты исходного кода и устранить ошибку. Также необходимо убедиться в неизменном отслеживании и анализе неудачных тестов. Игнорирование этого требования приведёт к лавинообразному увеличению неудачных тестовых результатов.
Экстремальное программирование.
Экстремальное программирование предполагает как один из постулатов использование инструментов автоматического модульного тестирования. Этот инструментарий может быть создан либо третьей стороной (например, Boost.Test), либо группой разработчиков данного приложения.
В экстремальном программировании используются модульные тесты для разработки через тестирование. Для этого разработчик до написания кода пишет тесты, отражающие требования к модулю. Очевидно, ни один из этих тестов до написания кода работать не должен. Дальнейший процесс сводится к написанию кратчайшего кода, удовлетворяющего данному набору тестов.
Интеграционное тестирование (англ. Integration testing, иногда называется англ. Integration and Testing, аббревиатура англ. I&T) - одна из фаз тестирования программного обеспечения, при которой отдельные программные модули объединяются и тестируются в группе. Обычно интеграционное тестирование проводится после модульного тестирования и предшествует системному тестированию.
Интеграционное тестирование в качестве входных данных использует модули, над которыми было проведено модульное тестирование, группирует их в более крупные множества, выполняет тесты, определённые в плане тестирования для этих множеств, и представляет их в качестве выходных данных и входных для последующего системного тестирования.
Целью интеграционного тестирования является проверка соответствия проектируемых единиц функциональным, приёмным и требованиям надежности. Тестирование этих проектируемых единиц - объединения, множества или группы модулей - выполняется через их интерфейс, с использованием тестирования "чёрного ящика".
Для автоматизации интеграционного тестирования применяются системы непрерывной интеграции (англ. Continuous Integration System, CIS). Принцип действия таких систем состоит в следующем:
· при изменении исходных кодов в репозитории производится обновление локального хранилища;
· выполняются необходимые проверки и модульные тесты;
· исходные коды компилируются в готовые выполняемые модули;
· выполняются тесты интеграционного уровня;
· генерируется отчет о тестировании.
Таким образом, автоматические интеграционные тесты выполняются сразу же после внесения изменений, что позволяет обнаруживать и устранять ошибки в короткие сроки.
Системное тестирование программного обеспечения - это тестирование программного обеспечения (ПО), выполняемое на полной, интегрированной системе, с целью проверки соответствия системы исходным требованиям. Системное тестирование относится к методам тестирования чёрного ящика, и, тем самым, не требует знаний о внутреннем устройстве системы.
Основной задачей системного тестирования является проверка как функциональных, так и не функциональных требований к системе в целом. При этом выявляются дефекты, такие как неверное использование ресурсов системы, непредусмотренные комбинации данных пользовательского уровня, несовместимость с окружением, непредусмотренные сценарии использования, отсутствующая или неверная функциональность, неудобство использования и т.д. Для минимизации рисков, связанных с особенностями поведения системы в той или иной среде, во время тестирования рекомендуется использовать
окружение максимально приближенное к тому, на которое будет установлен продукт после выдачи.
Можно выделить два подхода к системному тестированию:
на базе требований (requirements based)
Для каждого требования пишутся тестовые случаи (test cases), проверяющие выполнение данного требования.
на базе случаев использования (use case based)
· модульное тестирование (юнит-тестирование) - тестируется минимально возможный для тестирования компонент, например, отдельный класс или функция. Часто модульное тестирование осуществляется разработчиками ПО;
· интеграционное тестирование - тестируются интерфейсы между компонентами, подсистемами или системами. При наличии резерва времени на данной стадии тестирование ведётся итерационно, с постепенным подключением последующих подсистем;
· системное тестирование - тестируется интегрированная система на её соответствие требованиям;
· альфа-тестирование - имитация реальной работы с системой штатными разработчиками, либо реальная работа с системой потенциальными пользователями/заказчиком. Чаще всего альфа-тестирование проводится на ранней стадии разработки продукта, но в некоторых случаях может применяться для законченного продукта в качестве внутреннего приёмочного тестирования. Иногда альфа-тестирование выполняется под отладчиком или с использованием окружения, которое помогает быстро выявлять найденные ошибки. Обнаруженные ошибки могут быть переданы тестировщикам для дополнительного исследования в окружении, подобном тому, в котором будет использоваться ПО;
· бета-тестирование - в некоторых случаях выполняется распространение предварительной версии (в случае проприетарного ПО иногда с ограничениями по функциональности или времени работы) для некоторой большей группы лиц с тем, чтобы убедиться, что продукт содержит достаточно мало ошибок. Иногда бета-тестирование выполняется для того, чтобы получить обратную связь о продукте от его будущих пользователей.
Часто для свободного/открытого ПО стадия альфа-тестирования характеризует функциональное наполнение кода, а бета-тестирования - стадию исправления ошибок. При этом как правило на каждом этапе разработки промежуточные результаты работы доступны конечным пользователям.
Тестирование программных средств.
Качество продукта зависит, прежде всего, от качества процесса производства данного продукта (в случае программного обеспечения, процесса разработки программного обеспечения) и от знаний, навыков и мотивации разработчиков-производителей (аналитиков, архитекторов, программистов, менеджеров проектов и т.д.) продукта. Таким образом, пути повышения качества программного обеспечения - улучшение процессов, обучение людей и т.д. Программное обеспечение также необходимо проверять, т.е. тестировать.
Тестирование используется во многих областях человеческой деятельности: в науке тестируют гипотезы и теории при помощи наблюдений и экспериментов, в ходе обучения тестируются студенты, в производстве тестируется продукция.
Цели тестирования - продемонстрировать то, что программное обеспечение делает то, что нужно, и обнаружить ошибки до того момента, когда оно будет передано в использование. При тестировании обычно запускают программу, используя при этом тестовые данные. Далее проверяются результаты тестирования на нахождение ошибок и аномалий или также на контроль нефункциональных свойств. С помощью тестирования можно найти ошибки, но не доказать их отсутствие. Тестирование является частью более широкого процесса валидации (проверка достоверности) и верификации.
Типичный процесс тестирования изображен на рисунке 4.
Рисунок 4
В соответствии с тестовыми случаями выбираются тестовые данные (вход) и дополнительно фиксируется, какое в случае этих данных должно быть поведение системы или какой должен быть выход. Систему запускают с выбранными тестовыми данными, и результат сравнивают с ожидаемым результатом / поведением. Если система вела себя, как и ожидалось, тест считают пройденным. Если нет, то ошибка обнаружена. Для регистрирования результатов теста составляется отчет. В чем точно заключается ошибка, должны выяснить разработчики и затем ее исправить.