Ориентация на пример приложения

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

Обратите внимание, что в этом руководстве предполагается, что вы уже знакомы с рабочим процессом дерева исходного кода платформы. Если нет, обратитесь к https://source.android.com/source/requirements. Описанный здесь пример — это написание нового инструментального теста с целевым пакетом, установленным в собственном пакете тестового приложения. Если вы не знакомы с этой концепцией, прочтите введение в тестирование платформы .

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

  • фреймворки/база/пакеты/оболочка/тесты

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

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

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

См. дополнительные обсуждения исходного местоположения в сквозном примере для самоинструментирующих тестов .

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

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

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

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

Последняя версия файла манифеста для примера изменения gerrit доступна по адресу: https://android.googlesource.com/platform/frameworks/base/+/master/packages/Shell/tests/AndroidManifest.xml.

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

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

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

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

Так как это тестовый пакет приложения, независимый от тестируемого пакета приложения, необходимо использовать другое имя пакета: одно общее соглашение — добавлять суффикс .test .

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

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

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

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

android:targetPackage="com.android.shell"

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

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

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

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

Для более сложных тестов вам также необходимо написать файл конфигурации теста для тестовой системы Android, Trade Federation .

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

Последнюю версию файла конфигурации для примера изменения gerrit можно найти по адресу: frameworks/base/packages/Shell/tests/AndroidTest.xml.

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

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <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="ShellTests.apk"/>
</target_preparer>

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

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

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

Посмотрите здесь для получения дополнительной информации о конфигурациях тестового модуля.

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

Использование библиотеки android-support-test в качестве средства запуска тестов позволяет внедрять новые классы тестов в стиле JUnit4, а пример изменения gerrit содержит некоторые базовые возможности использования его функций.

Последний исходный код примера изменения gerrit доступен по адресу: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java.

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

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

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

В аннотации @SmallTest указан размер теста для всего тестового класса: все тестовые методы, добавленные в этот тестовый класс, наследуют эту аннотацию размера теста. установка класса перед тестированием, удаление после тестирования и удаление класса после тестирования: аналогично setUp и tearDown в JUnit4. Аннотации к Test используются для аннотирования фактического теста.

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

Аннотация @Before используется в методах JUnit4 для выполнения предтестовой настройки. Хотя в этом примере он не используется, существует также @After для демонтажа после тестирования. Точно так же аннотации @BeforeClass и @AfterClass могут использоваться в методах JUnit4 для выполнения настройки перед выполнением всех тестов в тестовом классе и последующего удаления. Обратите внимание, что методы настройки и демонтажа области класса должны быть статическими.

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

        Context context = InstrumentationRegistry.getTargetContext();

Поскольку тесты JUnit4 больше не требуют общего базового класса, больше нет необходимости получать экземпляры Context через getContext() или getTargetContext() через методы базового класса; вместо этого новый инструмент запуска тестов управляет ими через InstrumentationRegistry , где хранятся настройки контекста и среды, созданные инфраструктурой инструментирования. Через этот класс вы также можете вызвать:

  • getInstrumentation() : экземпляр класса Instrumentation
  • getArguments() : аргументы командной строки, переданные в am instrument через -e <key> <value>

Создавайте и тестируйте локально

Для наиболее распространенных случаев использования используйте Atest .

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