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