Пример самоинструментальных тестов

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

Это означает, что инструментальный тест не может внедриться в платформу Android, также известную как системный сервер, для выполнения. Для того , чтобы протестировать Android рамку, тестовый код может вызывать поверхности только общедоступный API, или тех , кто подвергается через Android Interface Definition Language AIDL доступны в исходном дереве платформы. Для этой категории тестов не имеет смысла настраивать таргетинг на какой-либо конкретный пакет. Таким образом, это обычное для таких инструментовок быть объявлен целевой свой собственный пакет тест приложений, как это определено в его собственном <manifest> тег AndroidManifest.xml .

В зависимости от требований пакеты тестовых приложений этой категории также могут:

  • Объедините действия, необходимые для тестирования.
  • Поделитесь идентификатором пользователя с системой.
  • Будьте подписаны с помощью ключа платформы.
  • Компилируется с исходным кодом фреймворка, а не с общедоступным SDK.

Эту категорию инструментальных испытаний иногда называют самооборудованием. Вот несколько примеров тестов самообучения в исходном коде платформы:

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

Прежде чем продолжить, рекомендуется сначала просмотреть код, чтобы получить общее представление.

Выбор местоположения источника

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

Если предположить , что корневой каталог для источника компоненты находится в <component source root> , большинство компонентов имеют в src и tests папки под ним, а также некоторые дополнительные файлы , такие как Android.mk (или разбить на дополнительный .mk файлы), файл манифест AndroidManifest.xml и файл конфигурации тестового «AndroidTest.xml».

Так как вы добавляете новый тест бренда, вы , вероятно , необходимо создать tests каталог рядом с компонентом src , и заполнить его содержимым.

В некоторых случаях, ваша команда может иметь дополнительные структуры каталогов в рамках tests из - за необходимость упаковать различные наборы тестов в отдельные файлы APK. И в этом случае, вам необходимо создать новый подкаталог под tests .

Независимо от структуры, вы в конечном итоге заполнение tests каталогов или вновь созданный подкаталог с файлами , похожими на то , что в instrumentation директории в образце изменения Геррита. В разделах ниже приводится более подробная информация о каждом файле.

Файл манифеста

Как и в случае с обычным приложением, каждому модулю инструментального тестирования требуется файл манифеста. Если имя файла как AndroidManifest.xml и обеспечить его рядом с Android.mk для тестового модуля, он будет получать автоматически включаются в BUILD_PACKAGE основной Makefile.

Прежде чем продолжить, настоятельно рекомендуется пройти через App Manifest Обзор первого.

Это дает обзор основных компонентов файла манифеста и их функций. Смотрите пример на platform_testing / тесты / например / приборы / AndroidManifest.xml .

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

Некоторые избранные примечания к файлу манифеста:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

package атрибут имя пакета приложения: это уникальный идентификатор , что Android рамочные приложения использует для идентификации приложения (или в этом контексте: ваше тестовое приложение). Каждый пользователь в системе может установить только одно приложение с этим именем пакета.

Кроме того, этот package атрибут такого же , как то , что ComponentName#getPackageName() возвращает, а также то же самое вы бы использовать для взаимодействия с различными pm команд подразделов через adb shell .

Также обратите внимание, что хотя имя пакета обычно имеет тот же стиль, что и имя пакета Java, на самом деле оно имеет очень мало общего. Другими словами, ваш пакет приложения (или теста) может содержать классы с любыми именами пакетов, хотя, с другой стороны, вы можете выбрать простоту и иметь имя пакета Java верхнего уровня в вашем приложении или тесте, идентичном имени пакета приложения.

android:sharedUserId="android.uid.system"

Это заявляет, что во время установки этому apk должен быть предоставлен тот же идентификатор пользователя, то есть идентификатор времени выполнения, что и базовой платформе. Обратите внимание , что это зависит от APK подписываются с тем же сертификатом в качестве основной платформы (см LOCAL_CERTIFICATE в предыдущем разделе), но они разные понятия:

  • некоторые разрешения или API защищены подписью, что требует того же сертификата подписи
  • некоторые разрешения или API , требуется system идентификации пользователя вызывающего абонента, который требует вызывающего пакета для акций идентификатора пользователя с system , если это отдельный пакет от самой основной платформы
<uses-library android:name="android.test.runner" />

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

android:targetPackage="android.test.example.helloworld"

Вы , возможно, заметили , что targetPackage здесь объявляется такой же , как package атрибут объявлен в manifest теге этого файла. Как уже упоминалось в тестирующих основы , эта категория Контрольно - измерительные приборы , как правило , предназначены для тестирования рамочные API, так что это не очень значимым для них , чтобы иметь конкретный целевой пакет приложений, другие потом сам.

Простой файл конфигурации

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

Сложный файл конфигурации

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

Конфигурация теста может указывать специальные параметры настройки устройства и аргументы по умолчанию для предоставления тестового класса. Смотрите пример на /platform_testing/tests/example/instrumentation/AndroidTest.xml .

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

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
  </test>
</configuration>

Некоторые избранные примечания к файлу конфигурации теста:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

Это указывает Trade Federation установить HelloWorldTests.apk на целевое устройство, используя указанный target_preparer. Разработчикам в Торговой федерации доступно множество целевых подготовителей, которые можно использовать для обеспечения правильной настройки устройства перед выполнением теста.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

Он определяет тестовый класс Trade Federation, который будет использоваться для выполнения теста, и передает пакет на устройство, которое будет выполнено, и среду выполнения тестов, которой в данном случае является JUnit.

Для получения дополнительной информации см Модуль тестирования Configs .

Возможности JUnit4

Использование android-support-test библиотеки испытателя бегун позволяет внедрение новых классов тестируемых JUnit4 стиля и образец изменение Геррита содержит некоторые основные использования его возможностей. Смотрите пример на /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java .

Хотя шаблоны тестирования обычно специфичны для команд компонентов, есть несколько общепринятых шаблонов использования.

@RunWith(JUnit4.class)
public class HelloWorldTest {

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

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

В @Before и @After аннотации используются на методах по JUnit4 выполнить предварительную настройку теста и после теста демонтажа. Подобным же образом , @BeforeClass и @AfterClass аннотации используются на методах по JUnit4 для выполнения настройки перед выполнением всех тестов в тестовом классе, и после демонтажа. Обратите внимание, что методы установки и удаления в области класса должны быть статическими. Что касается методов испытаний, в отличие от более ранней версии JUnit, они больше не нужно начинать имя методы с test , вместо этого, каждый из них должен быть аннотированный с @Test . Как обычно, методы тестирования должны быть общедоступными, не объявлять возвращаемое значение, не принимать параметров и вызывать исключения.

Важно: методы испытаний сами аннотированные с @Test аннотации; и обратите внимание , что для испытаний должны быть выполнены с помощью APCT, они должны быть аннотированный с размерами тест: пример аннотированный метод testHelloWorld в @SmallTest . Аннотация может применяться в области действия метода или класса.

Доступ к instrumentation

Хотя не охвачены в основном привет мир , например, это довольно обычное для Android тест требует доступа Instrumentation экземпляра: это интерфейс API ядра , который обеспечивает доступ к контексты приложений, деятельности API для тестирования , связанных с жизненным циклом и многое другое.

Не Поскольку JUnit4 не испытывает больше не требуется общий базовый класс, это больше не нужно , чтобы получить Instrumentation экземпляр через InstrumentationTestCase#getInstrumentation() , вместо того , новый тест бегун управляет им через InstrumentationRegistry где контекстные и экологические установки созданы основами приборных хранятся.

Чтобы получить доступ к экземпляру Instrumentation класса, просто вызовите статический метод getInstrumentation() на InstrumentationRegistry классе:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Сборка и тестирование локально

В большинстве случаев общего пользования, нанимают Atest .

Для более сложных случаев , требующих более тяжелые настройки, следуйте инструкциям КИП .