Основы тестирования Android приложений 2


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

Система тестирования Android включает в себя следующие особенности:

  • Наборы тестов Android основываются на JUnit. Для тестирования класса, который не использует Android API, можно использовать обычные тесты из JUnit, или использовать расширения Android JUnit, для тестирования Android компонентов. Если вы новичок в тестировании Android приложений, вы можете начать с классов тестов общего назначения, таких как AndroidTestCase и затем перейти к использованию более сложных классов.
  • Android расширения JUnit предоставляют компоненто-ориентированные классы тестов. Эти классы предоставляют вспомогательные методы для создания mock объектов и методов, которые помогают управлять жизненным циклом компонентов.
  • Наборы тестов содержатся в тестовых пакетах, которые похожи на основные пакеты программ, поэтому вам не придется изучать новый набор инструментов и методов для проектирования и создания тестов.
  • Инструменты SDK для создания и тестирования доступны в Eclipse с плагином ADT, а также в виде консольных приложений для использования с другими средами разработки. Эти инструменты получают информацию из проекта тестируемого приложения и используют ее для автоматического создания build файлов, файла манифеста и структуры каталогов для тестового пакета.
  • SDK также предоставляет monkeyrunner, API тестирования устройств с программами на Python, и UI/Application Exerciser Monkey(консольный инструмент для стресс-тестирования пользовательских интерфейсов путем отправки псевдо-случайных событий на устройство.

Этот документ описывает основы тестирования в среде Android: структуру тестов, API, который используется для разработки тестов, а также инструменты, которые используются для выполнения тестов и просмотра результатов. Документ предполагает, что у вас есть базовые знания в области программирования приложений для Android и методике тестирования JUnit.

На следующей диаграмме приведена система тестирования:

5_2

Структура теста

Android инструменты для сборки и тестирования предполагают, что тестовые проекты организованы в стандартную структуру тестов: классы тестов, тестовые пакеты и тестовые проекты.

Тестирование в Android основано на JUnit. В общем, тест JUnit является методом, который заявлен как часть тестируемого приложения. Вы организуете методы тестов в классы, называемые тестовыми случаями (test cases) (или наборами тестов (test suites)). Каждый тест является изолированным тестом отдельного модуля в тестируемом приложении. Каждый класс представляет собой контейнер для соответствующих методов тестов.

В JUnit, вы комплектуете один или несколько файлов исходников теста в один файл класса. Аналогичным образом в Android вы используете SDK build tools для компоновки одного или нескольких исходных файлов теста в файл класса в пакете теста Android. В JUnit вы используете исполнитель тестов (test runner) для выполнения тестов. В Android вы используете тестовые инструменты для загрузки пакета тестирования и тестируемого приложения, а затем выполняется Android test runner для запуска тестов.

Тестовые проекты

Тесты, как и Android приложения, организуются в проекты.

Тестовый проект является каталогом или Eclipse проектом, в котором вы создаете исходный код, файл манифеста, и другие файлы для тестового пакета. Android SDK содержит инструменты для Eclipse с ADT и для командной строки, которые создают и обновляют тестовые проекты для вас. Инструменты создают каталоги, которые вы используете для исходного кода, ресурсов и файл манифеста для тестового пакета. Консольные инструменты также создают Ant build файлы, которые нужны для сборки проекта.

Вам следует всегда использовать инструменты Android для создания тестового проекта. Преимущества инструментов:

  • Автоматическая настройка тестового пакета для использования InstrumentationTestRunner как исполнителя тестового случая. Вы должны использовать InstrumentationTestRunner (или подкласс) для запуска тестов JUnit.
  • Создание соответствующего имени для тестового пакета. Если тестируемое приложение имеет имя пакетаcom.mydomain.myapp, то инструменты Android сделают имя тестового пакета com.mydomain.myapp.test. Это поможет вам определить отношения и предотвратить конфликты в рамках системы.
  • Автоматическое создание надлежащих build файлов, файла манифеста, и структуры каталогов для тестового проекта. Это поможет вам построить тестовый пакет без изменения build файлов и установить связь между пакетом тестов и пакетом тестируемого приложения.

Вы можете создать тестовый проект в любом месте файловой системы, но лучшим подходом считается добавление тестового проекта так, чтобы его корневая директория tests/ находилась на том же уровне что и src/ каталог в проекте основного приложения. Это поможет вам найти тесты, связанные с приложением. Например, если корневым каталогом приложения проекта является MyProject, то вы должны использовать следующую структуру каталогов:

API тестирования

API тестирования Android основан на JUnit API и расширен instrumentation фреймворком и тестированием специфичных для Android классов.

JUnit

Вы можете использовать класс JUnit TestCase для тестирования объектов Java. TestCase также является базовым классом для AndroidTestCase, который можно использовать для тестирования Android-зависимых объектов. Помимо предоставления JUnit фреймворка, AndroidTestCase предлагает специфичные для Android настройки, сброс и вспомогательные методы.

Вы можете использовать класс JUnit Assert для отображения результатов теста. Методы утверждения (assert methods) сравнивают значения, ожидаемые от теста, с фактическим результатам и вызывает исключение, если сравнение не удается. Android также предоставляет класс утверждений, который расширяет возможные типы сравнений, и другой класс утверждений для тестирования пользовательского интерфейса. Они описаны более подробно в разделе Assertion классы.

Чтобы узнать больше о JUnit, вы можете прочитать документацию на домашней странице junit.org. API тестирования Android поддерживает стиль кода JUnit 3, но не JUnit 4. Кроме того, вы должны использовать исполнитель тестов Android –InstrumentationTestRunner для запуска классов теста. Этот исполнитель тестов описан в разделе Исполнение тестов.

Instrumentation

Android instrumentation представляет собой набор методов управления или “хуки” в системе Android. Эти хуки управляют компонентом Android независимо от его нормального жизненного цикла. Они также управляют тем, как Android запускает приложения.

Как правило, компонент Android работает в жизненном цикле, который определяется системой. Например, жизненный цикл объекта Activity начинается тогда, когда Activity активируется с помощью Intent. Сначала вызывается метод OnCreate(), а затем onResume(). Когда пользователь запускает другое приложение, вызывается метод OnPause(). Если в коде Activity вызывается метод finish(), то вызывается метод OnDestroy(). Android API фреймворк не позволяет использовать эти методы обратного вызова напрямую в вашем коде, но вы можете сделать это с помощью instrumentation.

Кроме того, система запускает все компоненты приложения в одном процессе. Вы можете разрешить некоторым компонентам, таким как контент-провайдеры, запуск в отдельном процессе, но вы не можете заставить приложение запустить в том же процессе еще одно приложение, которое уже работает.

С Android instrumentation, вы можете использовать методы обратного вызова в коде тестов. Это позволяет запускать жизненный цикл компонентов шаг за шагом, как если бы вы работали с отладчиком. Следующий фрагмент кода теста демонстрирует, как это использовать для тестирования сохранения и восстановления состояния Activity:

Ключевой методом используемый здесь – getActivity(), который является частью instrumentation API. Тестируемая Activity не запускается до вызова этого метода. Вы можете настроить фикстуру теста заранее, а затем вызвать этот метод для запуска Activity.

Кроме того, instrumentation может загружать пакет тестирования и тестируемое приложения в одном процессе. Поскольку компоненты приложения и их тесты в том же процессе, тесты могут вызывать методы компонентов, а также изменять и проверять поля компонентов.

Классы тестовых наборов

Android предоставляет несколько классов тестовых наборов, которые расширяют TestCase и Assert и предоставляют специфичные для Android настройки, сброс и вспомогательные методы.

AndroidTestCase

AndroidTestCase – полезный общий класс тестовых случаев, особенно если вы только начинаете с тестированием Android. Он расширяет TestCase и Assert. Он обеспечивает стандартные для JUnit setUp() и tearDown() методы, также хорошо, как и все JUnit’s Assert методы. Кроме того, он предоставляет методы для проверки прав доступа (permissions), и метод, который защищает от утечек памяти, очищая определенные ссылки на класс.

Тестовые наборы компонентов

Ключевой особенностью фреймворка тестирования Android являются его классы тестовых наборов компонентов. Эти тестовые классы сопровождаются методами для установки и сброса фикстур и управления жизненным циклом компонент. Они также предоставляют методы для настройки mock объектов. Эти классы описываются в следующих темах:

Android не предоставляет отдельный тестовый класс для BroadcastReceiver. Вместо этого тест BroadcastReceiver производится путем тестирования компонента, который отправляет Intent объекты, чтобы убедиться, что BroadcastReceiver отвечает корректно.

ApplicationTestCase

ApplicationTestCase используется для настройки и сброса объектов Application. Эти объекты поддерживают глобальное состояние информации, которая распространяется на все компоненты пакета приложения. Этот набор тестов может быть полезен для проверки корректной настройки элемента <application> в файле манифеста. Однако следует отметить, что этот набор тестов не позволяет вам контролировать тестирование компонентов в пакете приложения.

InstrumentationTestCase

Если вы хотите использовать instrumentation методы в классе набора тестов, вы должны использоватьInstrumentationTestCase или один из его подклассов. Набор тестов для Activity расширяет этот базовый класс другими функциями, которые помогают в тестировании Activity.

Assertion классы

Поскольку тестовые классы Android расширяют JUnit, вы можете использовать assertion методы для отображения результатов тестов. Assertion метод сравнивает фактическое значение, возвращаемое тестом с ожидаемым значением и вызывает AssertionException если тест на сравнение не пройден. Использование assertions удобнее, чем запись в лог и обеспечивает лучшую производительность тестов.

Кроме методов класса JUnit Assert, API тестирования также предоставляет классы MoreAsserts и ViewAsserts:

MoreAsserts содержит более мощные asserts, такие как assertContainsRegex(String, String), который делает сравнение с помощью регулярных выражений.

ViewAsserts содержит полезные asserts для Views. Например, он содержит assertHasScreenCoordinates(View, View, int, int), который проверяет, есть ли View с конкретной X и Y позицией на видимом экране. Эти asserts, упрощают тестирование геометрии и выравнивания пользовательского интерфейса.

Классы mock объектов

Для облегчения внедрения зависимостей в тестирование, Android предоставляет классы, которые создают mock объекты системы, такие как объекты Context, объекты ContentProvider, объекты ContentResolver и объекты Service. Некоторые тестовые случаи также предоставляют mock объекты Intent. Вы используете эти mock объекты для изолирования тестов от остальной части системы и облегчения внедрения зависимостей для тестирования. Эти классы находятся в пакетах Javaandroid.test и android.test.mock.

Mock объекты изолируют тесты от работающей системы подавляя или переопределяя нормальную работу. Например,MockContentResolver заменяет нормальный resolver framework на свой локальный, который изолирован от остальной системы. MockContentResolver также подавляет метод notifyChange(Uri, ContentObserver, boolean) так, чтобы наблюдатель объектов вне тестовой среды случайно не сработал.

Классы mock объектов также способствуют внедрению зависимостей путем предоставления подкласса нормального объекта, который не является функциональным, за исключением ваших переопределений. Например, объект MockResourcesпредоставляет подкласс Resources, в котором все методы вызывают исключение при вызове. Для его использования необходимо переопределить только те методы, которые должны предоставлять информацию.

Классы mock объектов, доступные в Android:

Классы простых mock объектов
MockApplication, MockContext, MockContentProvider, MockCursor, MockDialogInterface, MockPackageManager иMockResources обеспечивают простую и удобную mock стратегию. Они подавляют версии соответствующих классов объектов системы, и все их методы вызывают исключение UnsupportedOperationException. Для их использования необходимо переопределить методы, нужные вам для того, чтобы обеспечить надлежащим образом mock зависимости.Примечание: MockContentProvider и MockCursor доступны в API начиная с level 8.

Объекты mock resolver
MockContentResolver обеспечивает изолированное тестирование контент-провайдеров, маскируя системный resolver framework. Вместо того чтобы искать в системе контент-провайдер для данной строки обращения,MockContentResolver использует свою собственную внутреннюю таблицу. Вы должны явно добавить обработчики (provider) в эту таблицу, используя addProvider(String, ContentProvider).С помощью этой особенности можно связать mock контент-провайдера со строкой обращения. Вы можете создать экземпляр реального обработчика (provider), но использовать в нем тестовые данные. Вы даже можете установить обработчик для строки обращения к null. По сути, объект MockContentResolver изолирует тесты от обработчиков, которые содержат реальные данные. Вы можете контролировать функции обработчика и можете предотвратить влияние тестов на реальные данные.

Контексты для тестирования

Android предоставляет два класса контекстов, которые полезны для тестирования:

  • IsolatedContext предоставляет изолированный Context, файлы, директории и операций с базами данных, которые используют этот контекст находятся в области тестов. Хотя его функциональность ограничена, этот контекст имеет достаточно заглушек, чтобы реагировать на системные вызовы.Этот класс позволяет тестировать операции работы с данными приложения без ущерба для реальных данных, которые могут находиться на устройстве.
  • RenamingDelegatingContext обеспечивает контекст, в котором большинство функций обрабатываются в существующем контексте, но операции с файлами и базами данных обрабатываются в IsolatedContext. Изолированная часть использует директорию тестов и создает специальные имена файлов и каталогов. Вы можете контролировать именование или позволить конструктору определить их автоматически. Этот объект предоставляет быстрый способ создать изолированные области для операций с данными, сохраняя при этом нормальную функциональность для всех других операций в контексте.

Запуск тестов

Наборы тестов запускаются с помощью класса исполнителя тестов, который загружает класс с набором тестов, настраивает, выполняет и сбрасывает настройки для каждого теста. Android test runner также должен быть instrumented, поэтому системная утилита для запуска приложений может управлять загрузкой тестовых случаев из пакета тестов и загрузкой тестируемого приложения. Указать Android какой из instrumented test runner использовать можно установив значение в файле манифеста тестового пакета.

InstrumentationTestRunner является основным классом исполнителя тестов Android. Он расширяет исполнитель тестов JUnit, и он также instrumented. Он может запускать любой тестовый случай, предоставляемый Android и поддерживает все возможные типы тестирования.

InstrumentationTestRunner или его подкласса указывается в файле манифеста тестового пакета, в элементеinstrumentation. Кроме того, код InstrumentationTestRunner находится в разделяемой библиотеке android.test.runner, которая обычно не связана с кодом Android. Чтобы включить ее, необходимо указать это в элементе uses-library. Вам не нужно настраивать эти элементы самим. Eclipse с ADT или инструмент командной строки создает их автоматически и добавляет их в файл манифеста тестового пакета.

Примечание: Если вы используете исполнитель тестов отличный от InstrumentationTestRunner, нужно указать класс, который вы хотите использовать в <instrumentation>.

Для запуска InstrumentationTestRunner, используются внутренние классы системы вызываемые инструментами Android. При запуске теста в Eclipse с ADT, классы вызываются автоматически. При запуске теста из командной строки, эти классы запускаются с помощью Android Debug Bridge (adb).

Системные классы загружают и запускают тестовый пакет, убивают все процессы, запущенные экземпляром тестируемого приложения, а затем загружают новый экземпляр тестируемого приложения. Затем они проходят контроль наInstrumentationTestRunner, который проходит каждый класс теста в тестовом пакете. Вы также можете контролировать, какие тесты и методы выполнять с помощью параметров в Eclipse с ADT, или используя флаги с инструментом командной строки.

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

Чтобы узнать больше о запуске тестов прочитайте темы тестирование в Eclipse с ADT или тестирование в других IDE.

Просмотр результатов теста

Android фреймворк тестирования возвращает результаты тестов обратно в инструмент, который начинал тестирование. Если вы запустите тест в Eclipse с ADT, результаты будут отображаются в новой панели просмотра JUnit. Если вы запустите тест с помощью командной строки, результаты будет отображен в STDOUT. В обоих случаях вы увидите резюме теста, которое отображает имя каждого тестового случая и метод, который был запущен. Вы также увидите все неудачи assertions, которые произошли. Они включают указатели на строки в тестовом коде, где произошел сбой. Так же в списке будут указаны assertions неудачи с ожидаемым значением и фактическим значением.

Результаты тестов имеют специфичный для каждой IDE формат. Формат результатов тестов для Eclipse с ADT описан вТестирование в Eclipse с ADT. Формат результатов тестов при запуске из командной строки описан в Тестирование в других IDE.

monkey и monkeyrunner

SDK предоставляет два инструмента для функционального тестирования приложений:
UI/Application Exerciser Monkey, обычно называют “monkey”, это инструмент командной строки, который посылает псевдослучайные потоки нажатий клавиш, прикосновений, жесты в устройство. Запускается он с помощью инструментаAndroid Debug Bridge (adb). Он используется для стресс-тестирования вашего приложения и сообщает об ошибках, которые встречаются. Вы можете повторить поток событий, запуская инструмент каждый раз.

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

Работа с именами пакетов

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

Название Android пакета – это уникальное системное имя для .apk файла, указывается в атрибуте "android:package"элемента <manifest> в манифесте пакета. Название тестового Android пакета должно отличаться от названия Android пакета тестируемого приложения. По умолчанию, инструменты Android создают имя тестового пакета путем добавления “.test” к имени пакета тестируемого приложения.

Тестовый пакет также использует имя Android пакета для указания целевого пакета приложения для тестирования. Это устанавливается в атрибуте "android:targetPackage" элемента <instrumentation> в манифесте тестового пакета.

Идентификатор пакета Java применяется к исходному файлу. Это имя пакета отражает путь к каталогу исходного файла. Это также влияет на видимость классов и членов друг другу.

Инструменты Android, которые создают тестовый проект, дают имя пакету Android за вас. Из вводимых вами данных, инструменты настраивают имя тестового пакета и имя целевого пакета для тестируемого приложения. Для работы этих инструментов проект приложения должен уже существовать.

По умолчанию, эти инструменты устанавливают идентификатор пакета Java для тестового класса таким же, как идентификатор Android пакета. Не изменяйте имя Java пакета создаваемого классом R.java в тестовом пакете, потому что будет конфликт с классом R.java в тестируемом приложении. Не изменяйте имя тесового пакета Android, чтобы оно было таким же, как у тестируемого приложения, потому что тогда их имена уже не будут уникальными в системе.

Что тестировать

В теме What to Test описаны ключевые функции которые нужно протестировать в приложении Android, а также ключевые ситуации, которые могут повлиять на эти функции.

В большинстве своем модульное тестирование специфично для Android компонента, который тестируется. В темахТестирование Activity, Тестирование контент-провайдеров, Тестирование сервисов есть раздел, озаглавленный “What to Test”, в котором перечислены возможные области тестирования.

Если это возможно, вы должны запускать тесты на фактических устройства. Если это невозможно, вы можете использовать эмулятор Android с AVD настроенным на оборудование, экран, и версию, которую вы хотите протестировать.

Следующие шаги

Чтобы узнать, как настроить и запустить тесты в Eclipse, пожалуйста, обратитесь к Testing in Eclipse, with ADT. Если вы не работаете в Eclipse, обратитесь к Testing in Other IDEs.

Если вам нужно пошаговое введение в тестирование Android, изучите один из учебников по тестированию или пример пакета теста:

  • В учебнике Hello, Testing рассматриваются основные понятия и процедуры тестирования в контексте приложения Hello, World.
  • Учебник Activity Testing является отличным дополнением учебника Hello, Testing. Он проведет вас через более комплексное тестирование сценариев, которые можно разрабатывать в отношении более реалистичного приложения.
  • Пример тестового пакета Alarm Service Test является примером тестирования службы. Он содержит набор модульных тестов для примера приложения Alarm Service.

Источник

Перевод kraY


Оставьте комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

2 мыслей про “Основы тестирования Android приложений