Test porównawczy w ciągłej integracji

Możesz przeprowadzać testy porównawcze w trybie ciągłej integracji (CI), aby śledzić wydajność w i rozpoznawaj spadki lub poprawy skuteczności przed wersji aplikacji. Ta strona zawiera podstawowe informacje o analizie porównawczej w CI.

Zanim zaczniesz korzystać z testów porównawczych w CI, zastanów się, w jaki sposób ocena wyników różni się od wyników zwykłych testów.

Wyniki przybliżone

Testy porównawcze są testami zdecentralizowanymi, więc wyniki nie są tylko zaliczone lub nie. Testy porównawcze pozwalają zmierzyć czas na różnych urządzeniach, na których działają. Wykresy wyników w czasie pozwalają monitorować zmiany i obserwować szumy do systemu pomiaru.

Używaj prawdziwych urządzeń

przeprowadzać testy porównawcze na fizycznych urządzeniach z Androidem. Mogą wyświetlać się za pomocą emulatorów, zdecydowanie odradzamy stosowanie ich, ponieważ nie pozwalają one na dla użytkowników i zamiast tego podaje liczby powiązane z systemem operacyjnym hosta i sprzętem funkcje zabezpieczeń. Zastanów się nad użyciem prawdziwych urządzeń lub usługi, która umożliwia przeprowadzanie testów na rzeczywistych urządzeniach, np. w Laboratorium Firebase.

Przeprowadzanie testów porównawczych

Przeprowadzanie testów porównawczych w ramach potoku CI może różnić się od uruchamiania lokalnie w Android Studio. Lokalnie korzystasz z systemu Android testów integracji z 1 zadaniem connectedCheck Gradle. To zadanie automatycznie skompiluje Twój pakiet APK i przetestuje go oraz przeprowadzi testy na podłączonych urządzeniach lub serwer CI. W przypadku CI przepływ ten trzeba zwykle podzielić na i osobnych faz.

Budowanie

W przypadku biblioteki mikrotestów uruchom zadanie Gradle assemble[VariantName]AndroidTest, który tworzy testowy pakiet APK zawierający zarówno w przypadku kodu aplikacji, jak i testowanego kodu.

Z kolei biblioteka Macrobenchmark wymaga utworzenia docelowego pliku APK testuj plik APK oddzielnie. Dlatego uruchom polecenie :app:assemble[VariantName] i :macrobenchmark:assemble[VariantName] zadań Gradle.

Zainstaluj i uruchom

Te kroki są zwykle wykonywane bez uruchamiania zadań Gradle. Uwaga: może być wyodrębniona w zależności od tego, czy korzystasz z usługi, która umożliwia przeprowadzanie testów na rzeczywistych urządzeniach.

Do instalacji użyj polecenia adb install i podaj testowy pakiet APK lub docelowy plik APK.

Uruchom polecenie instrumentu adb shell am, aby uruchomić wszystkie testy porównawcze:

adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Korzystając z biblioteki analizy porównawczej, używaj zwykłych androidx.test.runner.AndroidJUnitRunner jako uruchamiany instrument.

Możesz przekazać te same argumenty instrumentacji co w konfiguracji Gradle. przy użyciu -e argumentu. Wszystkie opcje argumentów instrumentacji znajdziesz tu: Argumenty instrumentacji mikrotestów lub Dodaj argumenty instrumentacji na potrzeby analizy porównawczej.

Możesz na przykład ustawić argument dryRunMode, aby uruchamiać testy porównawcze jako w ramach procesu weryfikacji żądania pull. Gdy ta flaga jest włączona, testy porównawcze są przeprowadzane tylko w jednej pętli, aby sprawdzać, czy działają; ale nie trwa zbyt długo.

adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Więcej informacji o uruchamianiu testy z instrumentacją z wiersza poleceń znajdziesz w sekcji Przeprowadzanie testów przy użyciu ADB.

Zablokuj zegary

Wtyczka Microbenchmark Gradle udostępnia polecenie ./gradlew lockClocks do pozwala zablokować zegary procesora urządzenia z dostępem do roota. Przydaje się to, by zapewnić stabilność gdy masz dostęp do urządzeń z dostępem do roota, np. „userdebug”. do tworzenia kampanii. Dostępne opcje wykonaj tę czynność za pomocą skryptu powłoki lockClocks.sh dostępnego w library's source.

Możesz uruchomić skrypt bezpośrednio na hoście z systemem Linux lub Mac albo przekazać za pomocą kilku poleceń adb:

adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh
adb shell /data/local/tmp/lockClocks.sh
adb shell rm /data/local/tmp/lockClocks.sh

Jeśli uruchomisz skrypt powłoki bezpośrednio na hoście, wysyła on te polecenia do z połączonego urządzenia.

Więcej informacji o tym, dlaczego warto blokować zegary procesora, znajdziesz w sekcji uzyskiwanie spójnych wyników testów porównawczych.

Zbierz wyniki

Dane wyjściowe bibliotek analizy porównawczej JSON wraz z śladami profilowania w katalogu urządzenia z Androidem po każdym teście porównawczym. Biblioteka Macrobenchmark generuje wiele plików śledzenia perfetto: po jednym na zmierzoną iterację każdego pętla MacrobenchmarkRule.measureRepeated. Test mikroporównawczy pozwala jednak tylko jeden plik śledzenia dla wszystkich iteracji każdej BenchmarkRule.measureRepeated Profilowanie plików śledzenia też jest przesyłane do w tym samym katalogu.

Zapisz i zlokalizuj pliki

Jeśli przeprowadzasz testy porównawcze za pomocą Gradle, te pliki są automatycznie kopiowane do w katalogu wyjściowym komputera hosta, build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/

Jeśli aplikacja działa bezpośrednio za pomocą polecenia adb, musisz pobrać pliki. ręcznie. Domyślnie raporty są zapisywane na urządzeniu w katalogu multimediów w pamięci zewnętrznej testowanej aplikacji. Dla wygody biblioteka drukuje ścieżkę i zapisać go w narzędziu Logcat. Pamiętaj, że folder wyjściowy może się różnić w zależności od wersji Androida, na której są prowadzone testy porównawcze.

Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Możesz też skonfigurować lokalizację, w której raporty analizy porównawczej są zapisywane urządzenia za pomocą argumentu instrumentacji additionalTestOutputDir. Ten a aplikacja musi mieć możliwość zapisu w tym folderze.

adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Na Androidzie 10 (poziom interfejsu API 29) i nowszym testy aplikacji są przeprowadzane w pamięci masowej piaskownicy domyślnie, co uniemożliwia aplikacji dostęp do plików spoza domeny katalogu aplikacji. Aby móc zapisać plik w katalogu globalnym, jako /sdcard/Download, przekaż następującą instrumentację :

-e no-isolated-storage true

Musisz też wyraźnie zezwolić na korzystanie ze starszych opcji pamięci masowej w aplikacji referencyjnej plik manifestu:

<application android:requestLegacyExternalStorage="true" ... >

Więcej informacji znajdziesz w artykule Tymczasowe wyłączenie miejsca na dane.

Pobieranie plików

Aby pobrać wygenerowane pliki z urządzenia, użyj aplikacji adb pull które pobiera określony plik do bieżącego katalogu na hoście:

adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Aby pobrać wszystkie zasoby typu benchmarkData z określonego folderu, sprawdź ten fragment:

# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull

Pliki śledzenia (.trace lub .perfetto-trace) są zapisywane w tym samym jako folder benchmarkData.json, więc możesz zbierać je w ten sam sposób.

Przykład danych analizy porównawczej

Biblioteki testu porównawczego generują pliki JSON zawierające informacje o urządzenia, na którym były testowane testy porównawcze, oraz rzeczywiste testy porównawcze na tych urządzeniach. ten fragment kodu reprezentuje wygenerowany plik JSON:

{
    "context": {
        "build": {
            "brand": "google",
            "device": "blueline",
            "fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
            "model": "Pixel 3",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": false,
        "cpuMaxFreqHz": 2803200000,
        "memTotalBytes": 3753299968,
        "sustainedPerformanceModeEnabled": false
    },
    "benchmarks": [
        {
            "name": "startup",
            "params": {},
            "className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
            "totalRunTimeNs": 4975598256,
            "metrics": {
                "timeToInitialDisplayMs": {
                    "minimum": 347.881076,
                    "maximum": 347.881076,
                    "median": 347.881076,
                    "runs": [
                        347.881076
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 0,
            "repeatIterations": 3,
            "thermalThrottleSleepSeconds": 0
        }
    ]
}

Dodatkowe materiały

. .