Testowanie mapowania

To krótkie wprowadzenie do mapowania testów i wyjaśnienie, jak rozpocząć konfigurowanie testów w projekcie Android Open Source Project (AOSP).

Informacje o mapowaniu testów

Mapowanie testów to podejście oparte na Gerrit, które umożliwia deweloperom tworzenie reguł testów przed i po przesłaniu bezpośrednio w drzewie źródłowym Androida oraz pozostawienie decyzji dotyczących gałęzi i urządzeń do przetestowania infrastrukturze testowej. Definicje mapowania testów 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 przeprowadzania testów przed przesłaniem w powiązanych katalogach. Dzięki mapowaniu testów możesz dodać ten sam zestaw testów do weryfikacji przed przesłaniem, wprowadzając minimalne zmiany w drzewie źródłowym Androida.

Oto kilka przykładów:

Mapowanie testów opiera się na platformie testowej Trade Federation (TF) do wykonywania testów i raportowania wyników.

Definiowanie grup testowych

Mapowanie testów grupuje testy w grupę testową. Nazwa grupy testowej może być dowolnym ciągiem znaków. Na przykład presubmit może być nazwą grupy testów, które mają być uruchamiane podczas weryfikowania zmian. Z kolei postsubmit może być nazwą testów używanych do weryfikowania kompilacji po scaleniu zmian.

Reguły skryptu kompilacji pakietu

Aby platforma testowa Trade Federation mogła uruchamiać moduły testowe dla danej kompilacji, moduły te muszą mieć ustawioną wartość test_suites dla Soong lub LOCAL_COMPATIBILITY_SUITE ustawioną dla Make na jeden z tych 2 zestawów:

  • general-tests jest przeznaczony do testów, które nie zależą od funkcji specyficznych dla urządzenia (takich jak sprzęt specyficzny dla dostawcy, którego większość urządzeń nie ma). Większość testów powinna znajdować się w zestawie general-tests, nawet jeśli są one specyficzne dla jednego ABI lub liczby bitów albo funkcji sprzętowych, takich jak HWASan (dla każdego ABI jest osobny cel test_suites), a nawet jeśli muszą być uruchamiane na urządzeniu.
  • device-tests jest przeznaczony do testów, które zależą od funkcji specyficznych dla urządzenia. Zazwyczaj te testy znajdują się w katalogu vendor/. Specyficzne dla urządzenia odnosi się tylko do funkcji, które są unikalne dla danego urządzenia, dlatego dotyczy to zarówno testów JUnit, jak i testów GTest (które zwykle powinny być oznaczane jako general-tests, nawet jeśli są specyficzne dla ABI).

Przykłady:

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

Konfigurowanie testów do uruchamiania w zestawie testów

Aby test mógł być uruchamiany w zestawie testów, musi spełniać te warunki:

  • Nie może mieć dostawcy kompilacji.
  • Po zakończeniu musi zwolnić miejsce, na przykład usuwając wszystkie tymczasowe pliki wygenerowane podczas testu.
  • Musi przywrócić ustawienia systemowe do wartości domyślnych lub pierwotnych.
  • Nie powinien zakładać, że urządzenie jest w określonym stanie, np. że jest gotowe do rootowania. Większość testów nie wymaga uprawnień roota. Jeśli test wymaga uprawnień roota, powinien to określić za pomocą RootTargetPreparer w pliku AndroidTest.xml, jak w tym przykładzie:

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
    

Tworzenie plików mapowania testów

W katalogu, który wymaga pokrycia testami, dodaj plik JSON TEST_MAPPINGpodobny do tego przykładu. Te reguły zapewniają, że testy będą uruchamiane podczas weryfikacji przed przesłaniem, gdy w tym katalogu lub w którymkolwiek z jego podkatalogów zostaną zmienione pliki.

Przykład

Oto przykładowy plik TEST_MAPPING (w formacie JSON, ale 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": "CtsDeqpTestCases",
      "options": [
        {
          // Use regex in include-filter which is supported in AndroidJUnitTest
          "include-filter": "dEQP-EGL.functional.color_clears.*"
        }
      ]
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

Ustaw atrybuty

W tym przykładzie, presubmit i postsubmit to nazwy poszczególnych grup testowych. Więcej informacji o grupach testowych znajdziesz w sekcji Definiowanie grup testowych.

Wartość atrybutu name może być nazwą modułu testowego lub nazwą testu integracyjnego Trade Federation name (ścieżką do pliku XML testu, np. uiautomator/uiautomator-demo) . Pamiętaj, że pole name nie może używać nazwy klasy ani nazwy metody testowej.namename Aby zawęzić zakres testów do uruchomienia, użyj opcji takich jak include-filter. Zobacz include-filter przykładowe użycie.

Ustawienie host testu wskazuje, czy test jest testem bez urządzenia uruchamianym na hoście. Wartością domyślną jest false, co oznacza, że test wymaga 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 do dopasowywania ścieżki względnej dowolnego pliku kodu źródłowego (względem katalogu zawierającego plik TEST_MAPPING). W przykładzie, test CtsWindowManagerDeviceTestCases jest uruchamiany przed przesłaniem tylko wtedy, gdy plik Java zaczyna się od Window lub Activity, i znajduje się w tym samym katalogu co TEST_MAPPING plik lub w którymkolwiek z jego podkatalogów. Ukośniki odwrotne (\) muszą być poprzedzone znakiem ucieczki, ponieważ znajdują się w pliku JSON.

Atrybut imports umożliwia uwzględnianie testów w innych plikach TEST_MAPPING bez kopiowania treści. Uwzględniane są też pliki TEST_MAPPING w katalogach nadrzędnych importowanej ścieżki. Mapowanie testów umożliwia importowanie zagnieżdżone. Oznacza to, że 2 pliki TEST_MAPPING mogą importować się nawzajem, a mapowanie testów może scalać uwzględnione testy.

Atrybut options zawiera dodatkowe opcje wiersza poleceń Tradefed.

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

tradefed.sh run commandAndExit [test_module] --help

Więcej informacji o tym, jak działają opcje, znajdziesz w artykule Obsługa opcji w Tradefed.

Weryfikacje TEST_MAPPING

Podczas przesyłania zmian, które modyfikują pliki TEST_MAPPING, uruchamiane są weryfikacje przed przesłaniem, aby zapewnić poprawność:

  • Weryfikacja wzorców plików: sprawdza, czy wszystkie wyrażenia regularne w file_patterns pasują do co najmniej 1 pliku w repozytorium. Nieaktualne wzorce, które nie pasują do żadnego pliku, powodują niepowodzenie weryfikacji.
  • Weryfikacja w czasie kompilacji: promuje ostrzeżenia dotyczące weryfikacji w czasie kompilacji, które kompilacja zbiera, do blokowania błędów przed przesłaniem w głównych gałęziach. Typowe ostrzeżenia:
    • Nieistniejące moduły: odwoływanie się do nazwy modułu testowego, która nie istnieje w bazie kodu, np. gdy nazwa zawiera błąd.
    • Nieprawidłowe importy: ścieżki odniesienia w imports, które nie istnieją lub nie zawierają pliku TEST_MAPPING.
    • Problemy ze schematem: używanie nieobsługiwanych kluczy lub nieprawidłowo sformatowanych struktur w konfiguracji JSON.

Uruchamianie testów za pomocą Atest

Aby lokalnie wykonać reguły testów przed przesłaniem:

  1. Przejdź do katalogu zawierającego plik TEST_MAPPING.
  2. Uruchom to polecenie:

    atest
    

Uruchamiane są wszystkie testy przed przesłaniem skonfigurowane w plikach TEST_MAPPING w bieżącym katalogu i jego katalogach nadrzędnych. Atest znajduje i uruchamia 2 testy przed przesłaniem (A i B).

Jest to najprostszy sposób na uruchomienie testów przed przesłaniem w plikach TEST_MAPPING w bieżącym katalogu roboczym (CWD) i katalogach nadrzędnych. Atest znajduje i używa pliku TEST_MAPPING w CWD i wszystkich jego katalogach nadrzędnych.

Struktura kodu źródłowego

Ten przykład pokazuje, jak skonfigurować pliki TEST_MAPPING w drzewie źródłowym:

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

Zawartość pliku src/TEST_MAPPING:

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

Zawartość pliku src/project_1/TEST_MAPPING:

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

Zawartość pliku src/project_2/TEST_MAPPING:

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

Określanie katalogów docelowych

Możesz określić katalog docelowy, aby uruchamiać testy w plikach TEST_MAPPING w tym katalogu. To polecenie uruchamia 2 testy (A, 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 testów po przesłaniu zdefiniowane w pliku TEST_MAPPING w src_path (domyślnie CWD) i jego katalogach nadrzędnych:

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

Uruchamianie tylko testów, które nie wymagają urządzenia

Możesz użyć opcji --host w Atest, aby uruchamiać tylko te testy skonfigurowane na hoście, które nie wymagają urządzenia. Bez tej opcji Atest uruchamia oba testy – te, które wymagają urządzenia, i te, które są uruchamiane na hoście bez urządzenia. Testy są uruchamiane w 2 osobnych zestawach:

atest [--test-mapping] --host

Identyfikowanie grup testowych

Możesz określić grupy testowe w poleceniu Atest. To polecenie uruchamia wszystkie testy postsubmit związane z plikami w katalogu src/project_1, który zawiera tylko 1 test (C).

Możesz też użyć :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ędnianie podkatalogów

Domyślnie uruchamianie testów w TEST_MAPPING za pomocą Atest powoduje uruchamianie tylko testów przed przesłaniem skonfigurowanych w pliku TEST_MAPPING w CWD (lub podanym katalogu) i jego katalogach nadrzędnych. Jeśli chcesz uruchamiać testy we wszystkich plikach TEST_MAPPING w podkatalogach, użyj opcji --include-subdir, aby wymusić na Atest uwzględnienie tych testów.

atest --include-subdir

Bez opcji --include-subdir Atest uruchamia tylko test A. Z opcją --include-subdir Atest uruchamia 2 testy (A, B).

Obsługa komentarzy na poziomie wiersza

Możesz dodać komentarz w formacie // na poziomie wiersza, aby uzupełnić plik TEST_MAPPING o opis ustawienia, które następuje. ATest i Trade Federation przetwarzają wstępnie TEST_MAPPING do prawidłowego formatu JSON bez komentarzy. Aby plik JSON był przejrzysty, obsługiwany jest tylko komentarz w formacie // na poziomie wiersza.

Przykład:

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