Ta kategoria testów z instrumentacją nie różni się zbytnio od testów kierowanych na zwykłe aplikacje na Androida. Warto pamiętać, że aplikacja testowa, która zawiera instrumentację, musi być podpisana tym samym certyfikatem co aplikacja, na którą jest kierowana.
Pamiętaj, że w tym przewodniku zakładamy, że masz już pewną wiedzę na temat przepływu pracy w drzewie źródłowym platformy. Jeśli nie, zapoznaj się z sekcją Wymagania. Przykładem jest napisanie nowego testu instrumentacji z pakietem docelowym ustawionym na własny pakiet aplikacji testowej. Jeśli nie znasz tego pojęcia, przeczytaj wprowadzenie do testowania platformy.
W tym przewodniku jako przykład posłuży nam ten test:
- frameworks/base/packages/Shell/tests
Zanim przejdziesz dalej, zapoznaj się z kodem, aby uzyskać ogólne pojęcie o tym, co się w nim znajduje.
Wybierz lokalizację źródłową
Ponieważ test instrumentacji będzie kierowany na aplikację, zgodnie z konwencją kod źródłowy testu należy umieścić w katalogu tests
w katalogu głównym źródła komponentu w drzewie źródłowym platformy.
Więcej informacji o lokalizacji źródła znajdziesz w przykładzie kompleksowym dotyczącym testów z samodzielnym instrumentowaniem.
Plik manifestu
Podobnie jak w przypadku zwykłej aplikacji każdy moduł testu instrumentacji potrzebuje pliku manifestu. Jeśli nazwiesz plik AndroidManifest.xml
i umieścisz go obok Android.mk
w module testowym, zostanie on automatycznie uwzględniony w głównym pliku make BUILD_PACKAGE
.
Zanim przejdziesz dalej, zdecydowanie zalecamy zapoznanie się z omówieniem pliku manifestu aplikacji.
Zawiera on omówienie podstawowych komponentów pliku manifestu i ich funkcji.
Najnowszą wersję pliku manifestu dla przykładowej zmiany w Gerrit można znaleźć pod adresem: https://android.googlesource.com/platform/frameworks/base/+/android16-release/packages/Shell/tests/AndroidManifest.xml
Dla wygody dołączyliśmy zrzut ekranu:
<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>
Kilka uwag na temat pliku manifestu:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell.tests">
Atrybut package
to nazwa pakietu aplikacji. Jest to unikalny identyfikator, którego platforma aplikacji na Androida używa do identyfikowania aplikacji (w tym kontekście: aplikacji testowej). Każdy użytkownik w systemie może zainstalować tylko jedną aplikację o danej nazwie pakietu.
Ponieważ jest to pakiet aplikacji testowej, niezależny od pakietu aplikacji podlegającej testowaniu, należy użyć innej nazwy pakietu. Jedną z powszechnych konwencji jest dodanie sufiksu .test
.
Ten atrybut package
jest taki sam jak wartość zwracana przez ComponentName#getPackageName()
i taki sam jak ten, którego używasz do interakcji z różnymi podpoleceniami pm
za pomocą adb shell
.
Pamiętaj też, że chociaż nazwa pakietu jest zwykle w tym samym stylu co nazwa pakietu Java, w rzeczywistości ma z nią niewiele wspólnego. Innymi słowy, pakiet aplikacji (lub testu) może zawierać klasy o dowolnych nazwach pakietów. Z drugiej strony możesz uprościć sprawę i użyć w aplikacji lub teście nazwy pakietu Java najwyższego poziomu, która będzie identyczna z nazwą pakietu aplikacji.
<uses-library android:name="android.test.runner" />
Jest to wymagane w przypadku wszystkich testów instrumentacji, ponieważ powiązane klasy są spakowane w osobnym pliku biblioteki JAR platformy, dlatego podczas wywoływania pakietu testowego przez platformę aplikacji wymagane są dodatkowe wpisy ścieżki klasy.
android:targetPackage="com.android.shell"
Ustawia to pakiet docelowy instrumentacji na com.android.shell
.
Gdy instrumentacja jest wywoływana za pomocą polecenia am instrument
, platforma ponownie uruchamia proces com.android.shell
i wstrzykuje do niego kod instrumentacji w celu przeprowadzenia testu. Oznacza to również, że kod testowy będzie miał dostęp do wszystkich instancji klas działających w testowanej aplikacji i może manipulować stanem w zależności od udostępnionych punktów zaczepienia testu.
Prosty plik konfiguracji
Każdy nowy moduł testowy musi mieć plik konfiguracyjny, który zawiera metadane modułu, zależności w czasie kompilacji i instrukcje pakowania, aby kierować systemem kompilacji. W większości przypadków wystarczy opcja pliku Blueprint opartego na Soongu. Więcej informacji znajdziesz w artykule Prosta konfiguracja testu.
Złożony plik konfiguracji
W przypadku bardziej złożonych testów musisz też napisać plik konfiguracji testu dla platformy testowej Androida, Trade Federation.
Konfiguracja testu może określać specjalne opcje konfiguracji urządzenia i domyślne argumenty, które mają być przekazywane do klasy testu.
Najnowszą wersję pliku konfiguracyjnego dla przykładowej zmiany w Gerrit można znaleźć pod adresem:frameworks/base/packages/Shell/tests/AndroidTest.xml
Dla wygody dołączyliśmy zrzut ekranu:
<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>
Kilka uwag na temat pliku konfiguracji testu:
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>
Informuje to Trade Federation, aby zainstalować plik ShellTests.apk na urządzeniu docelowym za pomocą określonego preparera docelowego. W Trade Federation deweloperzy mają do dyspozycji wiele narzędzi do przygotowywania urządzeń docelowych, które mogą służyć do zapewnienia prawidłowej konfiguracji urządzenia przed wykonaniem testu.
<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>
Określa klasę testową Trade Federation, która ma być używana do wykonania testu, oraz przekazuje pakiet na urządzenie, na którym ma być wykonany test, i platformę uruchamiającą testy, która w tym przypadku jest JUnit.
Więcej informacji o testowaniu konfiguracji modułów znajdziesz tutaj
Funkcje JUnit4
Używanie biblioteki android-support-test
jako narzędzia do uruchamiania testów umożliwia dostosowanie nowych klas testowych w stylu JUnit4, a przykładowa zmiana w Gerrit zawiera bardzo podstawowe wykorzystanie jej funkcji.
Najnowszy kod źródłowy przykładowej zmiany Gerrit jest dostępny pod adresem:frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
Wzorce testowania są zwykle specyficzne dla zespołów komponentów, ale istnieją pewne ogólnie przydatne wzorce użycia.
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {
Istotną różnicą w JUnit4 jest to, że testy nie muszą już dziedziczyć po wspólnej klasie testu podstawowego. Zamiast tego piszesz testy w zwykłych klasach Java i używasz adnotacji do wskazywania określonych ustawień i ograniczeń testu. W tym przykładzie informujemy, że ta klasa powinna być uruchamiana jako test JUnit4 na Androidzie.
Adnotacja @SmallTest
określa rozmiar testu dla całej klasy testowej: wszystkie metody testowe dodane do tej klasy testowej dziedziczą tę adnotację rozmiaru testu.
Konfiguracja przed klasą testową, wycofanie po teście i wycofanie po klasie testowej:
podobne do metod setUp
i tearDown
w JUnit4.
Adnotacja Test
służy do dodawania adnotacji do rzeczywistego testu.
@Before
public void setup() {
...
@Test
public void testGetProvider_shouldCacheProvider() {
...
Adnotacja @Before
jest używana w metodach przez JUnit4 do przeprowadzania konfiguracji przed testem.
W tym przykładzie nie jest używana funkcja @After
, która służy do wyłączania testu po jego zakończeniu.
Podobnie adnotacje @BeforeClass
i @AfterClass
mogą być używane w metodach przez JUnit4 do przeprowadzenia konfiguracji przed wykonaniem wszystkich testów w klasie testowej i do wyczyszczenia po ich zakończeniu. Pamiętaj, że metody konfiguracji i czyszczenia w zakresie klasy muszą być statyczne.
W przypadku metod testowych, w przeciwieństwie do wcześniejszej wersji JUnit, nie muszą one już zaczynać nazwy metody od test
. Zamiast tego każda z nich musi być opatrzona adnotacją @Test
. Jak zwykle metody testowe muszą być publiczne, nie mogą deklarować wartości zwracanej, nie mogą przyjmować parametrów i mogą zgłaszać wyjątki.
Context context = InstrumentationRegistry.getTargetContext();
Testy JUnit4 nie wymagają już wspólnej klasy bazowej, więc nie trzeba już uzyskiwać instancji Context
za pomocą getContext()
ani getTargetContext()
za pomocą metod klasy bazowej. Zamiast tego nowy program do uruchamiania testów zarządza nimi za pomocą InstrumentationRegistry
, w którym przechowywana jest konfiguracja kontekstowa i środowiskowa utworzona przez platformę instrumentacji. W ramach tej klasy możesz też wywoływać:
getInstrumentation()
: instancja klasyInstrumentation
getArguments()
: argumenty wiersza poleceń przekazane doam instrument
za pomocą-e <key> <value>
Kompilowanie i testowanie lokalnie
W przypadku najczęstszych zastosowań używaj funkcji Atest.
W bardziej złożonych przypadkach wymagających większego dostosowania postępuj zgodnie z instrukcjami dotyczącymi implementacji.