Essa categoria de teste de instrumentação não é muito diferente das de segmentação dos aplicativos Android comuns. Vale ressaltar que o aplicativo de teste que incluiu a instrumentação precisa ser assinado com o mesmo certificado do aplicativo de destino.
Este guia pressupõe que você já tenha algum conhecimento no fluxo de trabalho da árvore de origem da plataforma. Caso contrário, consulte os requisitos. O exemplo abordado aqui é criar um novo teste de instrumentação com é definido no próprio pacote de aplicativo de teste. Se você não conhece conceito, leia a Introdução aos testes de plataforma.
Este guia usa o seguinte teste como exemplo:
- frameworks/base/pacotes/Shell/testes
É recomendável navegar pelo código primeiro para ter uma boa impressão. antes de continuar.
Escolher um local de origem
Como o teste de instrumentação terá como destino um aplicativo, a convenção
é colocar o código-fonte do teste em um diretório tests
na raiz do
diretório de origem do componente na árvore de origem da plataforma.
Veja mais discussões sobre o local da fonte no exemplo completo para com autoinstrumentação.
Arquivo de manifesto
Assim como em um aplicativo normal, cada módulo de teste de instrumentação precisa de uma
arquivo de manifesto do app. Se você nomear o arquivo como AndroidManifest.xml
e fornecer em seguida
como Android.mk
para o tmodule de teste, ele será incluído automaticamente pelo
Makefile do núcleo BUILD_PACKAGE
.
Antes de continuar, recomendamos revisar Visão geral do manifesto do app primeiro.
Isso fornece uma visão geral dos componentes básicos de um arquivo de manifesto e as funcionalidades deles.
A versão mais recente do arquivo de manifesto para a mudança do Gerrit de amostra pode ser acessada em: https://android.googlesource.com/platform/frameworks/base/+/main/packages/Shell/tests/AndroidManifest.xml
Um snapshot está incluído aqui para sua conveniência:
<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>
Algumas observações selecionadas no arquivo de manifesto:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
O atributo package
é o nome do pacote do aplicativo: é o identificador
exclusivo que o framework do aplicativo Android usa para identificar um
aplicativo (ou, neste contexto, o aplicativo de teste). Cada usuário no sistema
só podem instalar um app com esse nome de pacote.
Como este é um pacote de aplicativo de teste independente do aplicativo,
pacote em teste, um nome de pacote diferente deve ser usado: uma convenção comum
é adicionar um sufixo .test
.
Além disso, o atributo package
é o mesmo
ComponentName#getPackageName()
retorna e também o mesmo que você usaria para interagir com várias sub-redes pm
usando adb shell
.
Embora o nome do pacote geralmente esteja no mesmo estilo, como um nome de pacote Java, ele tem poucas coisas a ver com ele. Em outras palavras, o pacote do aplicativo (ou teste) pode conter classes com qualquer mas, por outro lado, você pode optar pela simplicidade e ter seus nome do pacote Java de nível 2 em seu aplicativo ou teste idêntico ao do aplicativo nome do pacote.
<uses-library android:name="android.test.runner" />
Isso é necessário para todos os testes de instrumentação, já que as classes relacionadas são empacotadas em um arquivo de biblioteca jar separado, portanto, requer mais entradas do caminho de classe quando o pacote de teste é invocado pela estrutura do aplicativo.
android:targetPackage="com.android.shell"
Isso define o pacote de destino da instrumentação como com.android.shell
.
Quando a instrumentação é invocada pelo comando am instrument
, o framework
reinicia o processo com.android.shell
e injeta um código de instrumentação
o processo de execução do teste. Isso também significa que o código de teste terá
acesso a todas as instâncias de classe em execução no aplicativo em teste e poderá
manipular o estado, dependendo dos hooks de teste expostos.
Arquivo de configuração simples
Cada novo módulo de teste precisa ter um arquivo de configuração para direcionar o sistema de build com metadados do módulo, dependências de tempo de compilação e instruções de empacotamento. Na maioria dos casos, a opção de arquivo Blueprint baseada em Soong suficientes. Consulte Configuração de teste simples para ver detalhes.
Arquivo de configuração complexo
Para testes mais complexos, você também precisa criar uma configuração de teste para o arcabouço de testes do Android, a Trade Federation.
A configuração de teste pode especificar opções especiais de configuração do dispositivo e para fornecer a classe de teste.
A versão mais recente do arquivo de configuração da mudança de exemplo do Gerrit pode ser acessada em: frameworks/base/packages/Shell/tests/AndroidTest.xml
Um snapshot está incluído aqui por conveniência:
<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>
Algumas observações selecionadas sobre o arquivo de configuração de teste:
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>
Isso informa à Trade Federation para instalar o ShellTests.apk no destino. usando um target_preparer especificado. Há muitos preparadores de destino disponíveis para desenvolvedores na Trade Federation e podem ser usados para garantir o dispositivo está configurado corretamente antes da execução do teste.
<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>
Isso especifica a classe de teste da Trade Federation a ser usada para executar o teste e transmite o pacote no dispositivo a ser executado e o framework do executor de testes, que é o JUnit neste caso.
Confira mais informações sobre as Configurações de módulo de teste.
Recursos do JUnit4
O uso da biblioteca android-support-test
como executor de testes permite a adoção de novas
classes de teste no estilo JUnit4, e a mudança de exemplo do Gerrit contém um uso muito básico
dos recursos.
O código-fonte mais recente da mudança de exemplo do gerrit pode ser acessado em: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
Embora os padrões de teste geralmente sejam específicos para equipes componentes, há alguns e padrões de uso geralmente úteis.
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {
Uma diferença significativa no JUnit4 é que os testes não precisam mais herdam de uma classe de teste base comum. você escreve testes em Java simples e usam anotações para indicar certas configurações e restrições de teste. Em neste exemplo, instruímos que esta classe deve ser executada como um Android JUnit4.
A anotação @SmallTest
especificou um tamanho de teste para toda a classe de teste: todos.
métodos de teste adicionados a essa classe de teste herdam essa anotação de tamanho de teste.
configuração da classe pré-teste, desmontagem pós-teste e desmontagem da classe pós-teste:
semelhantes aos métodos setUp
e tearDown
no JUnit4.
A anotação Test
é usada para anotar o teste real.
@Before
public void setup() {
...
@Test
public void testGetProvider_shouldCacheProvider() {
...
A anotação @Before
é usada em métodos do JUnit4 para realizar a configuração pré-teste.
Embora não seja usado neste exemplo, também há @After
para a desmontagem pós-teste.
Da mesma forma, as anotações @BeforeClass
e @AfterClass
podem ser usadas em
do JUnit4 para realizar a configuração antes de executar todos os testes em uma classe de teste,
e desmontagem depois. Os métodos de configuração e eliminação do escopo de classe
deve ser estático.
Quanto aos métodos de teste, ao contrário da versão anterior do JUnit, eles não precisam mais
para iniciar o nome do método com test
, cada um deles precisa ser anotado
com @Test
. Como de costume, os métodos de teste precisam ser públicos, declarar nenhum valor de retorno,
não têm parâmetros e podem gerar exceções.
Context context = InstrumentationRegistry.getTargetContext();
Como os testes JUnit4 não exigem mais uma classe de base comum, ele não é mais
necessário para conseguir instâncias de Context
usando getContext()
ou
getTargetContext()
usando métodos da classe de base; o novo executor de testes
gerencia por meio de InstrumentationRegistry
em que a configuração contextual e ambiental criada pelo framework de instrumentação é
armazenados. Com esta classe, você também pode chamar:
getInstrumentation()
: a instância para a classeInstrumentation
getArguments()
: os argumentos de linha de comando transmitidos paraam instrument
via-e <key> <value>
Criar e testar localmente
Para os casos de uso mais comuns, use Atest:
Para casos mais complexos que exigem personalização mais complexa, siga as instruções de instrumentação.