ПРЕСС-ЦЕНТР

Тестирование встроенного программного обеспечения

Андрей Пронин, Вячеслав Ванюлин, Игорь Починок, Auriga, Inc., НИВЦ МГУ

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

Особенности тестирования встроенного программного обеспечения

Специфика встроенного программного обеспечения (ПО) задаёт определённые требования к организации процесса тестирования. С одной стороны, специалист по тестированию заметит много общего с процессом тестирования прикладного ПО, но, с другой стороны, выявит и немало отличий.

M2M вместо UI

Первое, что бросается в глаза, функциональность пользовательских интерфейсов обычно ограниченна: консольное текстовое меню, интерфейс командной строки, набор цифровых входов и выходов и, пожалуй, всё. С другой стороны, интерфейсы для M2M и межкомпонентного взаимодействия могут обладать обширными функциональными возможностями и быть очень сложными, например API для высокоуровневого ПО, различные сетевые протоколы для обмена данными и управления. Поэтому основной фокус при тестировании встроенного программного обеспечения смещается с тестирования пользовательских интерфейсов на тестирование компонентов, неочевидных для конечных пользователей.

Зависимость от оборудования

Второе существенное отличие – высокий уровень зависимости от аппаратного обеспечения. Даже в том случае, когда встроенное ПО построено на базе более-менее стандартного программного фреймворка, оно должно учитывать особенности конкретной аппаратной платформы. По определению, встроенное программное обеспечение разрабатывается для конкретного аппаратного модуля (или, что встречается чаще, комплекса аппаратных средств).

Зачастую подобные аппаратные модули разрабатываются одновременно с соответствующим встроенным ПО. Именно оно первым запускается на данном оборудовании. В отличие от сферы разработки приложений, в случае встроенного ПО у разработчика нет возможности быть уверенным в том, что операционная система была протестирована для конкретной аппаратной платформы или что возможности самой аппаратной платформы по исполнению различных программ были тщательным образом проверены. В результате разработанное программное обеспечение может содержать куски кода, специфичные для конкретных версий аппаратной платформы.

Работа встроенного ПО может зависеть от таких вещей, на которые инженеры, как правило, не обращают внимания при разработке прикладного ПО, например от длины кабеля, частоты последовательного порта или типа устройств, подключённых к шине обмена данными. Всё это делает успешную работу встроенного программного обеспечения в большей степени зависимой от конкретного аппаратного модуля или поведения других модулей в той же шине или сети.

По сравнению со стандартной разработкой, такие вещи, как «состояние гонки» (далее используется оригинальное название – «race conditions»), чаще всего вызываются не взаимодействием внутренних компонентов самого программного обеспечения, а взаимодействием программного обеспечения со средой. Таким образом, количество факторов и параметров, влияющих на работу встроенного ПО намного выше. Воспроизведение дефектов поэтому также гораздо сложнее.

Сложности обновления встроенного ПО

Процедуры поддержки, такие как развёртывание и обновление программного обеспечения, получение отладочной информации, также отличаются от того, что используется для традиционного прикладного программного обеспечения, где можно полагаться на plug-and-play, автоматическую конфигурацию, мастера установки, наличие удобного отладчика в IDE, или, по меньшей мере, можно сбросить лог-файл на диск.

В мире встроенного ПО обновления требуют перевода программного обеспечения в специальный режим, удаления EEPROM-защиты от записи , подключения к серверу раздачи файлов (например, TFTP), нескольких перезагрузок и тому подобных вещей. Таким образом, весь этот процесс весьма длителен и неудобен. Кроме того, может оказаться, что устройство хранения файлов поддерживает только ограниченное количество циклов перезаписи.

Поэтому на этапе активной разработки, версии, как правило, обновляются реже, чем это происходит для других видов ПО. Новые ревизии, как правило, развёртываются после того, как было исправлено значительное количество дефектов. Соответственно, главная задача тестирования на этом этапе – выявление как можно большего числа дефектов, не останавливая процесс после обнаружения первого, даже если он вызывает сбой продукта.

Необходимость промежуточных инструментов тестирования

Тестировать M2M-интерфейсы вручную невозможно. Поэтому перед началом тестирования встроенного ПО нам необходимо разработать специальные приложения агенты тестирования, которые позволяют создавать входной сигнал и получать ответ системы через доступные интерфейсы. Часто также требуется эмулировать специфические паттерны электрических сигналов на различных линиях передачи данных, чтобы протестировать поведение встроенного ПО в различных ситуациях. Для этого может использоваться специальный аппаратно-программный комплекс.

Ограниченная доступность оборудования

Учитывая высокий уровень зависимости от аппаратной платформы и тот факт, что встроенное программное обеспечение часто разрабатывается одновременно с самой платформой, стоит отметить некоторые важные последствия этого.

Во-первых, на момент активной разработки может быть готово к использованию лишь малое число образцов новейшего оборудования. Во-вторых, диапазон типов аппаратных модулей, для которых требуется выполнить тестирование ПО, может быть достаточно широким. Соответственно, команда тестировщиков вынуждена распределять это ограниченное количество аппаратных модулей между собой и/или организовывать удалённый доступ к ним. Во втором случае инженеры не имеют физического доступа к аппаратному обеспечению.

Проблемы с определением источника дефектов

При тестировании новой, только что разработанной аппаратной платформы обычно выявляется большое количество дефектов самого аппаратного обеспечения. При этом любой обнаруженный дефект может быть вызван как ПО, так и самой аппаратной платформой. Об этом важно постоянно помнить. Хуже всего то, что программное обеспечение может прекрасно работать с одной версией аппаратного модуля и иметь проблемы при работе с другой версией.

Высокая ценность каждого выявленного дефекта

Мы уже писали выше о том, что в случае с встроенным ПО дефекты воспроизвести сложнее. Именно поэтому каждый такой дефект ценен сам по себе, и обязанность тестировщика – собрать максимум информации о нём в момент выявления, так как второй раз воспроизвести его, возможно, удастся не скоро. В сочетании с очень ограниченными возможностями по отладке встроенного программного обеспечения это ставит перед инженерами дополнительные непростые задачи.

Ограничения, связанные с обновлениями программного обеспечения, требуют настойчивости и упорства в процессе тестирования, выявления максимального количества дефектов для каждой версии программного обеспечения, придают особую важность процессам сборки и развёртывания.

Высокие требования к автономности системы

Необходимость устойчивости системы к вводу некорректных данных и её автономности требует очень тщательного стрессового тестирования. Как следствие – требуется эмулировать последовательность быстро сменяющихся событий, чтобы проверить код на все возможные race conditions.

Основы подхода и платформы тестирования

Автоматизированное тестирование

Очевидно, что использование ручного тестирования в качестве основного метода для встроенного ПО практически нереализуемо. Необходимость проведения рутинного, длительного, повторяющегося стрессового тестирования; работа с M2M-интерфейсами; высокая потребность в выявлении race conditions для часто-сменяющихся событий,, а также ряд других факторов подводят нас к выводу, что поле боя остаётся за автоматизированным тестированием.

Конечно, всегда остаётся небольшой процент тестов, которые более выгодно проводить вручную, чем автоматизировать. Но этот процент ниже обычного, что объясняется более высокой относительной эффективностью автоматизации в среде с удалённым доступом и специальными средствами поддержки, которые будут описаны дальше. В любом случае автоматизация обычно успешно реализуется для более чем 95 % тестовых сценариев. При этом важно понимать, что автоматизация и использование агентов тестирования не просто изменяет способ выполнения тестовых сценариев и демонстрации результатов, но оказывает влияние на все аспекты процесса тестирования.

Проектирование тестов и отслеживание требований

Поскольку большинство тестовых сценариев в случае тестирования встроенного ПО не может быть выполнено вручную, стандартный подход к проектированию тестов (сбор требований, разработка тестовых сценариев, ручное тестирование, оптимизация, исправление, детализация, создание сценария на базе кейсов ручного тестирования) здесь не сработает.

Вместо этого на основании требований к встроенному ПО создаются два артефакта: набор тестовых сценариев и требования к тестовой среде, которая состоит из фреймворка автоматизации и агентов тестирования. Формально, требования к встроенному программному обеспечению преобразуются в тестовые сценарии, которые, в свою очередь, формируют требования к тестовой среде и агентам. Но на практике тестовые сценарии и требования к вспомогательному программному обеспечению не разделяются.

Валидация инфраструктуры для поддержки тестирования

Ещё один фактор, влияющий на процесс тестирования ПО, – это требование валидации самого вспомогательного ПО. Фактически, это означает, что вначале необходимо протестировать саму среду тестирования и агенты, то есть инженеры должны выполнить весь стандартный комплекс действий, включая проектирование тестов, их выполнение, анализ покрытия и др. Агенты тестирования, как правило, представляют собой достаточно простые программные решения с ограниченным набором требований, поэтому их тестирование намного проще, чем тестирование оригинального программного продукта. Тем не менее зачастую для них требуется внедрять сложные протоколы обмена данными (включая шифрование, аутентификацию, компрессию, установление соединения и др.), поэтому на деле их тестирование не такая уж простая задача.

Полноценное тестирование агентов часто невозможно при отсутствии более-менее рабочей версии целевого процесса. Таким образом, успешное прохождение теста агентом также означает успешное прохождение базовых функциональных тестов в определённой области для конечного ПО.

Во время этого тестирования широко используются верифицированные ранее агенты тестирования и инструменты отладки аппаратного обеспечения, такие как анализаторы шины, сетевые анализаторы пакетов, зонды JTAG и осциллоскопы. Средства отладки особенно эффективны на данном этапе, цель которого – получение приложения с базовым функционалом. Это ещё одно естественное следствие процесса разработки встроенного программного обеспечения. Разработка инструментов поддержки тестирования выполняется параллельно с проектированием проектного встроенного программного обеспечения, а планы разработки как целевого ПО, так и агентов тестирования в значительной степени зависят друг от друга.

Вторая составляющая процесса тестирования – среда автоматизированного тестирования – также требуется валидации. Тем не менее в отличие от агентов тестирования, которые выполняют функции, имеющие отношение к конкретному встроенному продукту, она может и должна проектироваться и реализовываться независимо от реального проекта, в рамках более широкого технологического или организационного сегмента. Такая реализация поможет существенно сократить трудовые издержки, а также отменит необходимость создания такой среды для каждого нового проекта.

Отслеживание и анализ дефектов

Кроме, собственно, самих процессов верификации и валидации, необходимость проведения валидации инфраструктуры поддержки тестирования оказывает сильное влияние на жизненный цикл дефектов и настройку репозитория отслеживания дефектов. Для встроенного программного обеспечения необходимо учитывать несколько возможных вариантов происхождения дефектов: конечное ПО, аппаратное обеспечение или инфраструктура поддержки тестирования. На практике это требует указания для каждого обнаруженного дефекта идентификаторов целевого ПО, аппаратного обеспечения и инструмента тестирования. Кроме того, рекомендуется включить представителя команды разработки вспомогательной инфраструктуры тестирования в рабочую группу по приоритизации задач при устранении дефектов (далее используется в оригинальном значении – triage committee).

Для поиска дефектов, вызванных аппаратным обеспечением, команда тестирования должна включать в себя специалиста с хорошими познаниями в области аппаратного обеспечения и опытом работы с различными инструментми по отладке аппаратного обеспечения, упомянутых выше. Этот специалист также должен входить в triage committee. В его задачи входит анализ каждого дефекта на предмет его возникновения вследствие проблем с аппаратным обеспечением, сбор и анализ дополнительных данных при возникновении предположений в аппаратном происхождении дефекта, а также консультирование команды тестирования в случае любого сомнительного поведения аппаратного обеспечения.

Матрица покрытия аппаратного обеспечения

Высокая вероятность выявления ошибок аппаратного обеспечения не означает, что всё исчерпывается только необходимостью указания идентификаторов оборудования в описании дефекта или включения инженера по аппаратному обеспечению в команду тестирования. Конечное ПО также необходимо протестировать на всех целевых типах и ревизиях аппаратного обеспечения. Это вовсе не означает, что каждый тестовый сценарий должен быть запущен на всех возможных модулях/типах/версиях аппаратного обеспечения. Необходимо сделать осознанный выбор между полнотой покрытия аппаратного обеспечения и трудозатратами. Зачастую возможно объединить модули аппаратного обеспечения в группы для тестирования каждой функциональной области или, по меньшей мере, произвести случайную выборку для регрессионного тестирования. При этом стратегии тестирования в разных проектах могут отличаться друг от друга в зависимости от требований и ограничений конкретного проекта.

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

Отслеживание сборок программного обеспечения

Правильно построенный процесс сборки и развёртывания программного обеспечения – существенный элемент успеха тестирования встроенного ПО. Крайне важно правильно идентифицировать сборку целевого ПО, для которой был обнаружен дефект. Для решения проблем, связанных с идентификацией сборки ПО, существует несколько методов.

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

Другой метод используется для smoke-тестов для стабильных версий ПО. На практике инфраструктура поддержки тестирования содержит в себе все необходимые инструменты для создания сборки, назначения ей уникального номера, маркировки её в дереве исходного кода, архивации бинарных файлов, передачи их на сервер развёртывания (TFTP-сервер) и затем на целевую плату, а также обновления ПО на плате. Все эти операции могут быть выполнены перед началом ночного smoke-теста для стабильной сборки ПО. Для проектов, не имеющих ограничений по количеству обновлений ПО для целевого аппаратного модуля, эти операции могут быть выполнены полностью (сборка и развёртывание на плате) или частично (только развёртывание) перед каждой сборкой, гарантируя тестирование правильной версии ПО.

Поддержка отладки

Помимо обнаружения максимального количества ошибок, качественно выстроенный процесс тестирования ставит своей целью также помощь разработчикам в исправлении дефектов. Согласитесь, дефект, найденный командой тестирования, имеет мало ценности, если он не может быть воспроизведён и, соответственно, исправлен командой разработчиков из-за отсутствия достаточной информации.

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

Эта ситуация приводит к двум важным следствиям. Во-первых, расписание и другие характеристики отладочных и стабильных сборок целевого ПО могут отличаться, и дефект, который зафиксирован в одной версии, может отсутствовать в другой. Поэтому так важно при тестировании отслеживать версии сборки программного обеспечения, в которых обнаружен дефект.

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

Прогоны тестов

В силу противоречивых характеристик встроенного программного обеспечения обычно предусматривается два вида прогонов тестов.

Идеальным методом является пакетный запуск прогона тестов. Все выбранные тестовые кейсы запускаются в соответствии с матрицей покрытия аппаратного обеспечения, а результаты сохраняются в протоколе тестирования. В случае обнаружения ошибки прогон теста не останавливается, но вместо этого собирается вся возможная информация о состоянии системы в момент обнаружения дефекта (и все способы поддержки отладки в этом случае обретают важность), а тестирование продолжается по следующему тестовому кейсу. Безусловно, фреймворк поддержки тестирования должен выполнять полную очистку системы после каждого тестового сценария, чтобы избежать влияния одного сценария на другой в общем и серии неудавшихся тестов после первого сбоя в частности. Этот процесс включает в себя перезагрузку системы, обычно – перезагрузку ПО после успешно выполненного кейса тестового сценария и перезагрузку аппаратного обеспечения после сбоя.

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

В отдельных случаях тесты прогоняются до первого сбоя. После ошибки прогон теста останавливается, а состояние системы консервируется. Разработчик получает уведомление и возможность детально изучить состояние системы, чтобы выявить причину, вызвавшую сбой. Кроме того, можно создать автоматизированную среду тестирования, которая позволит останавливать прогон теста только при сбое в определённом тестовом кейсе (или наборе кейсов). Такие прогоны тестов полезны, когда необходимо исследовать дефекты, для которых информация, собранная в пакетном режиме, недостаточна, так что разработчику требуется доступ к системе в момент проявления дефекта для её изучения.

Виртуальная лаборатория

Методологические подходы, описанные в предыдущих разделах, позволяют построить эффективный процесс тестирования встроенного программного обеспечения. Тем не менее есть и ещё одна важная часть этого процесса – программно-аппаратный комплекс «Виртуальная лаборатория» (Virtual Laboratory или VL). Данный комплекс предоставляет средства для решения некоторых технически сложных задач, с которыми можно столкнуться во время тестирования.

Во-первых, он включает в себя базу данных существующих аппаратных модулей, каждому из которых присвоен простой строковый идентификатор. Для каждого модуля можно указать несколько признаков, таких как версия аппаратного обеспечения, идентификаторы канала связи: IP-адрес, MAC-адрес, логин и пароль к системе и т.д. Для тестового сценария это означает, что, зная идентификатор модуля, он может восстановить все остальные признаки, необходимые для коммуникации с данной платой и предоставить полноценный отчёт о дефектах.

Во-вторых, VL поддерживает работу с последовательными консолями, стойками питания (устройства, позволяющие включать и выключать питание на целевых аппаратных модулях), реле с сухими контактами. Соответствующие консоли/реле/стойки указаны для конкретных модулей в базе данных, что позволяет тестовым сценариям исполнять любые операции с конкретным модулем, зная только его имя.

В-третьих, VL обеспечивает возможности для получения исключительного доступа к совместно используемому аппаратному оборудованию. Перед подключением к консоли конкретного модуля тестовый сценарий должен сначала «заблокировать» данный модуль при помощи специальной команды. Когда модуль заблокирован, ни одна другая сущность не может «заблокировать» его. После окончания процесса тестирования тестовый сценарий «разблокирует» модуль, предоставляя возможность контроля другим участникам тестирования. Подобный механизм блокировки взаимоисключающего доступа предотвращает случайные попытки прогона тестов в одно и то же время на одной и той же плате разными сценариями или операторами.

VL предоставляет удобный для пользователя интерфейс командной строки через защищённое подключение и может использоваться как тестовыми сценариями, так и специалистами-операторами. VL это база для выполнения всех автоматизированных и ручных тестов для целевого программного обеспечения.

Краткие выводы

Тестирование встраиваемого программного обеспечения может быть достаточно трудоёмким и сложным процессом, а дефекты – воспроизводиться с трудом. Выделив время на создание правильной тестовой среды и выстраивание надлежащего процесса тестирования, вы добьётесь наилучших результатов.

10 главных проблем автоматизации, которые необходимо решить при тестировании встраиваемого ПО

1. Физический доступ к встроенной системе для проведения тестирования или получения результатов.Для датчиков и некоторых других аппаратных интерфейсов, возможно, потребуются особые условия доступа.

2. Возможности поддержки автоматизации тестирования в самом продукте. Перехватчики, ловушки для подключения тестовых средств или вызываемые API-интерфейсы должны быть добавлены в код продукта изначально.

3. Верификация поведения. Рекомпиляция встроенного кода на ПК часто влияет на время прогона.

4. Доступность оборудования. Проводите верификационные тесты на оригинальном оборудовании. Автоматизация на симуляторе не заменяет тестирования непосредственно на устройстве.

5. Безопасность. Любой код тестирования (или агент) во встроенной системе, в частности в выпускаемой версии, не должен оставлять возможностей для её взлома.

6. Вопросы временных характеристик. В некоторые устройства встроено ПО, зависимое от контроллеров времени.

7. Эксперты в команде. Команде нужны люди, подкованные как в технологии, так и в тестировании.

8. Автоматизация мультимедийных компонентов. Неважно, что это – воспроизведение звуков или мигание светодиодов, – всё должно быть протестировано.

9. Ограничения памяти. Бывают ситуации, когда оперативной памяти слишком мало, что вызывает сбой системы.

10 Недетерминизм тестируемой системы. Благодаря целому ряду причин (race conditions, генераторы случайных чисел, состояние системы) тестируемая система может вести себя по-разному в разные прогоны тестов, что существенно затрудняет тестовое покрытие и прохождение критериев Pass/Fail.

Источник: LogiGear