Mapowanie testowe

Oto krótkie wprowadzenie do mapowania testów i wyjaśnienie, jak łatwo rozpocząć konfigurowanie testów w ramach projektu Android Open Source Project (AOSP).

Mapowanie testowe

Mapowanie testów to podejście oparte na Gerrit, które pozwala programistom tworzyć reguły testów przed i po przesłaniu bezpośrednio w drzewie źródłowym Androida, a decyzje dotyczące gałęzi i urządzeń pozostawiają samej infrastrukturze testowej. Definicje mapowania testowego to pliki JSON o nazwie TEST_MAPPING, które można umieścić w dowolnym katalogu źródłowym.

Atest może używać plików TEST_MAPPING do uruchamiania testów przed przesłaniem w powiązanych katalogach. Dzięki mapowaniu testów możesz dodać ten sam zestaw testów, aby wstępnie przesłać testy, wykonując prostą zmianę w drzewie źródłowym Androida.

Zobacz te przykłady:

Dodaj testy przed przesłaniem do TEST_MAPPING for services.core

Dodaj testy przed przesłaniem do narzędzia TEST_MAPPING dotyczące narzędzi/deteksu za pomocą importu

Przeprowadzanie testów i raportowanie wyników korzysta z zapasu testowego federacji handlowej (TF).

Zdefiniuj grupy testowe

Testuj grupy mapowania za pomocą grupy testowej. Nazwa grupy testowej może być dowolnym ciągiem znaków. Na przykład wstępne przesyłanie może dotyczyć grupy testów, które mają być uruchomione podczas weryfikowania zmian. Za pomocą testów postsubmit można zweryfikować kompilacje po scaleniu zmian.

Reguły skryptu tworzenia pakietu

Aby zasilacz testów federacji handlowej mógł uruchamiać moduły testowe mapowania testów w przypadku danej kompilacji, moduły te muszą mieć ustawiony parametr test_suites dla Soong lub LOCAL_COMPATIBILITY_SUITE dla ustawienia Make w jednym z tych 2 zestawów:

  • testy ogólne – testy, które nie opierają się na funkcjach urządzenia (np. testy dotyczące konkretnego dostawcy sprzętu, którego większość urządzeń nie ma). Większość testów powinna należeć do zestawu testów ogólnych, nawet jeśli dotyczą one jednego interfejsu ABI, bity lub funkcji sprzętowych, takich jak HWASan (dla każdego interfejsu ABI istnieje oddzielny cel pakietów testowych), nawet jeśli muszą być uruchamiane na danym urządzeniu.
  • testy-urządzenia – testy, które opierają się na funkcjach urządzenia. Zazwyczaj te testy są dostępne w domenie vendor/. Termin „właściwy dla urządzenia” nie odnosi się do funkcji ABI czy SoC, które mogą mieć inne urządzenia, lecz do funkcji charakterystycznych dla urządzenia a, dlatego dotyczy ono dokładnie tak wielu testów natywnych GTest, jak general-tests, nawet jeśli są one związane z interfejsem ABI.

Przykłady:

Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests

Konfigurowanie testów w zestawie testowym

Aby test został uruchomiony w ramach zestawu testów, wykonaj następujące czynności:

  • nie może mieć żadnego dostawcy kompilacji.
  • należy wyczyścić dane po jego zakończeniu, np. usunąć pliki tymczasowe wygenerowane podczas testu.
  • zmienić ustawienia systemu na wartość domyślną lub pierwotną.
  • nie powinny zakładać, że urządzenie jest w określonym stanie, np. z dostępem do roota. Większość testów nie wymaga uprawnień roota. Jeśli test musi wymagać uprawnienia użytkownika root, powinien określić, że w parametrze AndroidTest.xml jest RootTargetPreparer, jak w tym przykładzie:
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>

Tworzenie testowych plików mapowania

W przypadku katalogu, który wymaga pokrycia testu, wystarczy dodać plik JSON TEST_MAPPING podobny do poniższego przykładu. Te reguły sprawią, że testy będą przeprowadzane w ramach kontroli przed przesłaniem, gdy dotkniesz jakiegoś pliku w tym katalogu lub jego podkatalogach.

Skorzystaj z przykładu

Oto przykładowy plik TEST_MAPPING (jest on w formacie JSON z obsługą komentarzy):

{
  "presubmit": [
    // JUnit test with options and file patterns.
    {
      "name": "CtsWindowManagerDeviceTestCases",
      "options": [
        {
          "include-annotation": "android.platform.test.annotations.RequiresDevice"
        }
      ],
      "file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
    },
    // Device-side GTest with options.
    {
      "name" : "hello_world_test",
      "options": [
        {
          "native-test-flag": "\"servicename1 servicename2\""
        },
        {
          "native-test-timeout": "6000"
        }
      ]
    }
    // Host-side GTest.
    {
      "name" : "net_test_avrcp",
      "host" : true
    }
  ],
  "postsubmit": [
    {
      "name": "CtsWindowManagerDeviceTestCases"
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

Ustaw atrybuty

W tym przykładzie presubmit i postsubmit to nazwy każdej grupy testowej. Więcej informacji o grupach testowych znajdziesz w artykule Definiowanie grup testowych.

Nazwę modułu testowego lub nazwy testu integracji federacji handlowej (ścieżka zasobu do testowego pliku XML, np. uiautomator/uiautomator-demo) można ustawić w wartości atrybutu name. Pamiętaj, że pole name nie może używać klasy name ani metody testowej name. Aby zawęzić zakres testów, możesz użyć opcji takich jak include-filter. Patrz przykładowe użycie filtra include.

Ustawienie host testu wskazuje, czy test dotyczy testu bez urządzeń uruchomionego na hoście. Wartość domyślna to false (fałsz), co oznacza, że test wymaga uruchomienia urządzenia. Obsługiwane typy testów to HostGTest w przypadku plików binarnych GTest i HostTest w przypadku testów JUnit.

Atrybut file_patterns umożliwia ustawienie listy ciągów wyrażeń regularnych, które odpowiadają ścieżce względnej dowolnego pliku z kodem źródłowym (względem katalogu zawierającego plik TEST_MAPPING). W powyższym przykładzie test CtsWindowManagerDeviceTestCases zostanie uruchomiony przed przesłaniem tylko wtedy, gdy jakikolwiek plik Java zaczyna się od tekstu Window lub Activity, który znajduje się w tym samym katalogu co plik TEST_MAPPING lub dowolny z jego podkatalogów. Ukośniki lewe muszą być zmieniane tak, jak w pliku JSON.

Atrybut importy pozwala uwzględnić testy w innych plikach TEST_MAPPING bez kopiowania ich treści. Pamiętaj, że uwzględnione zostaną też pliki TEST_MAPPING w katalogach nadrzędnych zaimportowanej ścieżki. Mapowanie testowe umożliwia importowanie zagnieżdżonych. Oznacza to, że 2 pliki TEST_MAPPING mogą się ze sobą importować, a mapowanie testowe umożliwia prawidłowe scalanie uwzględnionych testów.

Atrybut options zawiera dodatkowe opcje wiersza poleceń TradeFed.

Aby uzyskać pełną listę opcji dostępnych w przypadku danego testu, uruchom polecenie:

tradefed.sh run commandAndExit [test_module] --help

Więcej informacji o działaniu opcji znajdziesz w artykule Obsługa opcji podlegających obrocie w ramach handlu detalicznego .

Przeprowadzanie testów w narzędziu Atest

Aby lokalnie wykonać reguły testu wstępnego:

  1. Przejdź do katalogu z plikiem TEST_MAPPING.
  2. Uruchom polecenie:
atest

Uruchomione są wszystkie testy wstępnego przesyłania skonfigurowane w plikach TEST_MAPPING bieżącego katalogu i jego katalogów nadrzędnych. Atest znajdzie i przeprowadzi 2 testy przed przesłaniem (A i B).

To najprostszy sposób wykonywania testów przed przesłaniem plików TEST_MAPPING w bieżącym katalogu roboczym i katalogach nadrzędnych. Atest znajdzie i użyje pliku TEST_MAPPING w CWD i wszystkich jego katalogach nadrzędnych.

Kod źródłowy struktury

Przykład poniżej pokazuje, jak można skonfigurować pliki TEST_MAPPING w drzewie źródłowym.

src
├── project_1
│   └── TEST_MAPPING
├── project_2
│   └── TEST_MAPPING
└── TEST_MAPPING

Treść src/TEST_MAPPING:

{
  "presubmit": [
    {
      "name": "A"
    }
  ]
}

Treść src/project_1/TEST_MAPPING:

{
  "presubmit": [
    {
      "name": "B"
    }
  ],
  "postsubmit": [
    {
      "name": "C"
    }
  ],
  "other_group": [
    {
      "name": "X"
    }
  ]}

Treść src/project_2/TEST_MAPPING:

{
  "presubmit": [
    {
      "name": "D"
    }
  ],
  "import": [
    {
      "path": "src/project_1"
    }
  ]}

Określ katalogi docelowe

Możesz podać katalog docelowy, w którym będziesz przeprowadzać testy w plikach TEST_MAPPING w tym katalogu. Poniższe polecenie uruchomi 2 testy (A i B).

atest --test-mapping src/project_1

Uruchamianie reguł testów po przesłaniu

Możesz też użyć tego polecenia, aby uruchomić reguły testu postsubmit zdefiniowane w zadaniu TEST_MAPPING w środowisku src_path (domyślnie jest to CWD) i w jego katalogach nadrzędnych:

atest [--test-mapping] [src_path]:postsubmit

Przeprowadzaj tylko testy, które nie wymagają urządzenia

Możesz użyć opcji --host dla Atest, aby uruchomić tylko testy skonfigurowane na hoście niewymagającym urządzenia. Bez tej opcji Atest przeprowadzi oba testy – te, które wymagają urządzenia, oraz te uruchomione na hoście, które nie wymagają urządzenia. Testy odbędą się w 2 osobnych zestawach.

atest [--test-mapping] --host

Określ grupy testowe

Grupy testowe możesz określić w poleceniu Atest. Poniższe polecenie uruchomi wszystkie testy postsubmit związane z plikami w katalogu src/project_1, który zawiera tylko jeden test (C).

Możesz też użyć polecenia :all, aby uruchomić wszystkie testy niezależnie od grupy. To polecenie uruchamia 4 testy (A, B, C, X):

atest --test-mapping src/project_1:all

Uwzględnij podkatalogi

Domyślnie testy w trybie TEST_MAPPING z użyciem metody Atest będą uruchamiać tylko testy przed przesłaniem skonfigurowane w pliku TEST_MAPPING w CWD (lub w podanym katalogu) i jego katalogach nadrzędnych. Jeśli chcesz przeprowadzać testy we wszystkich plikach TEST_MAPPING w podkatalogach, użyj opcji --include-subdir, aby wymusić w Atest uwzględnienie tych testów.

atest --include-subdir

Bez opcji --include-subdir Atest uruchomi tylko test A. W przypadku opcji --include-subdir Atest przeprowadzi 2 testy (A i B).

Komentarze na poziomie wiersza są obsługiwane

Możesz dodać komentarz w formacie // na poziomie wiersza, aby dopracować plik TEST_MAPPING z opisem ustawienia poniżej. ATest i federacja handlu detalicznego przetworzą wstępnie TEST_MAPPING do prawidłowego formatu JSON bez komentarzy. Aby zapewnić czysty i czytelny plik JSON, obsługiwany jest tylko komentarz w formacie // na poziomie wiersza.

Przykład:

{
  // For presubmit test group.
  "presubmit": [
    {
      // Run test on module A.
      "name": "A"
    }
  ]
}