Эта категория инструментальных тестов ничем не отличается от тестов, ориентированных на обычные приложения Android. Стоит отметить, что тестовое приложение, включающее инструментальные тесты, должно быть подписано тем же сертификатом, что и приложение, на которое они направлены.
Обратите внимание, что это руководство предполагает, что у вас уже есть некоторые знания о рабочем процессе с деревом исходного кода платформы. Если нет, обратитесь к разделу «Требования» . В данном примере рассматривается создание нового инструментального теста с целевым пакетом, заданным в качестве отдельного пакета тестового приложения. Если вы не знакомы с этой концепцией, ознакомьтесь с разделом «Введение в тестирование платформы» .
В этом руководстве в качестве образца используется следующий тест:
- фреймворки/база/пакеты/оболочка/тесты
Рекомендуется сначала просмотреть код, чтобы получить общее представление, прежде чем продолжить.
Определите местоположение источника
Поскольку тест инструментария будет нацелен на приложение, принято размещать исходный код теста в каталоге tests
в корневом каталоге исходного кода компонента в дереве исходного кода платформы.
Дополнительные обсуждения о местоположении источника см. в примере сквозного тестирования с самоинструментацией .
Файл манифеста
Как и обычному приложению, каждому тестовому модулю инструментальной части требуется файл манифеста. Если вы назовёте файл AndroidManifest.xml
и укажете его рядом с Android.mk
для вашего тестового модуля, он будет автоматически включён в основной make-файл BUILD_PACKAGE
.
Прежде чем продолжить, настоятельно рекомендуется сначала ознакомиться с обзором манифеста приложения .
Здесь представлен обзор основных компонентов файла манифеста и их функций.
Последнюю версию файла манифеста для примера изменения gerrit можно получить по адресу: https://android.googlesource.com/platform/frameworks/base/+/android16-release/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" />
Это требуется для всех тестов инструментария, поскольку связанные классы упакованы в отдельный файл библиотеки jar фреймворка, поэтому требуются дополнительные записи classpath, когда тестовый пакет вызывается фреймворком приложения.
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 доступно множество препараторов target, которые можно использовать для правильной настройки устройства перед выполнением теста.
<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>
Это определяет тестовый класс Trade Federation, который будет использоваться для выполнения теста, и передает пакет на устройство, которое будет выполняться, а также фреймворк запуска тестов, которым в данном случае является 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 для настройки перед выполнением всех тестов в тестовом классе и завершения тестирования после него. Обратите внимание, что методы setup и teardown в области действия класса должны быть статическими.
Что касается тестовых методов, в отличие от более ранней версии JUnit, им больше не нужно начинать имя с test
, вместо этого каждый из них должен быть аннотирован @Test
. Как обычно, тестовые методы должны быть публичными, не объявлять возвращаемого значения, не принимать параметров и могут вызывать исключения.
Context context = InstrumentationRegistry.getTargetContext();
Поскольку тесты JUnit4 больше не требуют общего базового класса, больше нет необходимости получать экземпляры Context
через getContext()
или getTargetContext()
через методы базового класса; вместо этого новый исполнитель тестов управляет ими через InstrumentationRegistry
, где хранятся настройки контекста и среды, созданные фреймворком Instrumentation. Через этот класс также можно вызывать:
-
getInstrumentation()
: экземпляр классаInstrumentation
-
getArguments()
: аргументы командной строки, переданныеam instrument
через-e <key> <value>
Сборка и тестирование локально
Для наиболее распространенных случаев использования используйте Atest .
Для более сложных случаев, требующих более серьезной настройки, следуйте инструкциям по использованию приборов .