Android udostępnia wiele narzędzi i interfejsów API, które mogą pomóc w tworzeniu testów różne rozmiary ekranów i okna.
Zastąpienie konfiguracji urządzenia
Funkcja kompozycyjna DeviceConfigurationOverride
umożliwia zastąpienie
atrybutów konfiguracji do testowania różnych rozmiarów ekranów i okien w Compose
układy. Zastąpienie ForcedSize
pasuje do dowolnego układu w dostępnym miejscu.
który pozwala uruchomić
Test interfejsu na dowolnym ekranie Na przykład możesz użyć małego telefonu
do uruchamiania wszystkich testów UI, w tym testów UI na duże telefony, urządzenia składane
na tabletach.
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
) {
MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
}
Za pomocą tej funkcji możesz też ustawić skalę czcionki, motywy które warto przetestować w oknach o różnych rozmiarach.
Robolectric
Użyj Robolectric, aby uruchomić w środowisku JVM narzędzie Compose lub testy interfejsu oparte na wyświetlaniu lokalnie – nie są wymagane żadne urządzenia ani emulatory; Możesz skonfigurować Robolectric, aby korzystać z określonych rozmiarów ekranów i innych przydatnych właściwości.
W tym przykładzie z Teraz na Androidzie rozwiązanie Robolectric zostało skonfigurowane. emulację rozmiaru ekranu 1000 x 1000 dp z rozdzielczością 480 dpi:
@RunWith(RobolectricTestRunner::class)
// Configure Robolectric to use a very large screen size that can fit all of the test sizes.
// This allows enough room to render the content under test without clipping or scaling.
@Config(qualifiers = "w1000dp-h1000dp-480dpi")
class NiaAppScreenSizesScreenshotTests { ... }
Możesz też ustawić kwalifikatory z treści testowej tak, jak w tym fragmencie kodu przykład Now na Androidzie:
val (width, height, dpi) = ...
// Set qualifiers from specs.
RuntimeEnvironment.setQualifiers("w${width}dp-h${height}dp-${dpi}dpi")
Pamiętaj, że RuntimeEnvironment.setQualifiers()
aktualizuje system i
zasobów aplikacji z nową konfiguracją, ale nie aktywuje żadnego działania
na aktywne aktywności lub inne elementy.
Więcej informacji znajdziesz w dokumentacji konfiguracji urządzenia Robolectric.
Urządzenia zarządzane przez Gradle
Wtyczka Androida do obsługi Gradle dla urządzeń zarządzanych przez Gradle (GMD) pozwala zdefiniować specyfikacje emulatorów i prawdziwych urządzeń, testów instrumentowanych. Utwórz specyfikacje dla urządzeń z różne rozmiary ekranów, aby wdrożyć strategię testowania, w ramach której na ekranach o określonych rozmiarach. za pomocą GMD z ciągłą integracją (CI), możesz zadbać o to, aby w razie potrzeby uruchomić odpowiednie testy udostępnianie i uruchamianie emulatorów oraz uproszczenie konfiguracji CI.
android {
testOptions {
managedDevices {
devices {
// Run with ./gradlew nexusOneApi30DebugAndroidTest.
nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) {
device = "Nexus One"
apiLevel = 30
// Use the AOSP ATD image for better emulator performance
systemImageSource = "aosp-atd"
}
// Run with ./gradlew foldApi34DebugAndroidTest.
foldApi34(com.android.build.api.dsl.ManagedVirtualDevice) {
device = "Pixel Fold"
apiLevel = 34
systemImageSource = "aosp-atd"
}
}
}
}
}
Kilka przykładów GMD znajdziesz w projekcie testing-samples.
Laboratorium Firebase
Skorzystaj z Laboratorium Firebase (FTL) lub podobnej usługi farmy urządzeń, by przeprowadzić na konkretnych urządzeniach, do których możesz nie mieć dostępu, takich jak na urządzeniach składanych lub tabletach o różnych rozmiarach; Laboratorium Firebase to płatna na poziomie bezpłatnym. FTL umożliwia też przeprowadzanie testów na emulatorach. Usługi te zwiększają niezawodność i szybkość testów instrumentalnych, ponieważ mogą wcześniej zapewnić obsługę urządzeń i emulatorów.
Informacje o korzystaniu z FTL w połączeniu z GMD znajdziesz w sekcji Skalowanie testów z użyciem GMD Urządzenia zarządzane przez Gradle
Testowanie filtrowania za pomocą mechanizmu uruchamiania testów
Optymalna strategia testowa nie powinna sprawdzać tego samego elementu dwukrotnie, dlatego większość Testy interfejsu nie muszą być przeprowadzane na różnych urządzeniach. Zwykle filtrujemy UI wszystkie lub większość z nich przeprowadza się na telefonach komórkowych, a tylko w niektórych przypadkach. urządzeń o różnych rozmiarach ekranów.
Możesz dodawać adnotacje do testów, które mają być uruchamiane tylko na określonych urządzeniach, a potem zakończone argument w AndroidJUnitRunner za pomocą polecenia, które uruchamia testów.
Możesz na przykład utworzyć różne adnotacje:
annotation class TestExpandedWidth
annotation class TestCompactWidth
Użyj ich w różnych testach:
class MyTestClass {
@Test
@TestExpandedWidth
fun myExample_worksOnTablet() {
...
}
@Test
@TestCompactWidth
fun myExample_worksOnPortraitPhone() {
...
}
}
Następnie możesz użyć usługi android.testInstrumentationRunnerArguments.annotation
do filtrowania określonych elementów. Jeśli na przykład jesteś
na urządzeniach zarządzanych przez Gradle:
$ ./gradlew pixelTabletApi30DebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Jeśli nie używasz GMD i zarządzasz emulatorami w CI, najpierw upewnij się, że odpowiedni emulator lub urządzenie jest gotowy i podłączony, a następnie przekazuje parametr za pomocą jednego z poleceń Gradle, które pozwalają uruchomić testy instrumentowane:
$ ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Pamiętaj, że urządzenie do espresso (patrz następna sekcja) może też filtrować testy, stosując właściwości urządzenia.
Ekspres do kawy
Za pomocą Espresso Device możesz wykonywać działania na emulatorach w testach, używając dowolnego typu testów instrumentalnych, w tym testów Espresso, Compose i UI Automator. Mogą one obejmować ustawianie rozmiaru ekranu lub przełączanie stanów urządzenia składanego. ani różnych stanów. Możesz na przykład sterować składanym emulatorem i ustawiać go na trybu stołu. Urządzenie do espresso zawiera też reguły JUnit i adnotacje do wymagają pewnych funkcji:
@RunWith(AndroidJUnit4::class)
class OnDeviceTest {
@get:Rule(order=1) val activityScenarioRule = activityScenarioRule<MainActivity>()
@get:Rule(order=2) val screenOrientationRule: ScreenOrientationRule =
ScreenOrientationRule(ScreenOrientation.PORTRAIT)
@Test
fun tabletopMode_playerIsDisplayed() {
// Set the device to tabletop mode.
onDevice().setTabletopMode()
onView(withId(R.id.player)).check(matches(isDisplayed()))
}
}
Pamiętaj, że urządzenie Espresso jest wciąż w fazie alfa i oferuje następujące funkcje: wymagania:
- Wtyczka Androida do obsługi Gradle w wersji 8.3 lub nowszej
- Emulator Androida w wersji 33.1.10 lub nowszej
- Urządzenie wirtualne z Androidem, na którym działa interfejs API na poziomie 24 lub wyższym
Filtruj testy
Urządzenie do espresso może odczytywać właściwości połączonych urządzeń, by umożliwić Ci filtrowanie testów z użyciem adnotacji. Jeśli wymagania z adnotacjami nie są spełnione, są pomijane.
Wymaga adnotacji trybu urządzenia
Adnotacji RequiresDeviceMode
można używać wiele razy, aby wskazać,
test, który będzie przeprowadzany tylko wtedy, gdy obsługiwane będą wszystkie wartości DeviceMode
na urządzeniu.
class OnDeviceTest {
...
@Test
@RequiresDeviceMode(TABLETOP)
@RequiresDeviceMode(BOOK)
fun tabletopMode_playerIdDisplayed() {
// Set the device to tabletop mode.
onDevice().setTabletopMode()
onView(withId(R.id.player)).check(matches(isDisplayed()))
}
}
Wymaga adnotacji displayowej
Adnotacja RequiresDisplay
umożliwia określenie szerokości i wysokości
ekranu urządzenia za pomocą klas rozmiaru, które definiują segmenty wymiarów.
zgodnie z oficjalnymi klasami dotyczącymi rozmiaru okna.
class OnDeviceTest {
...
@Test
@RequiresDisplay(EXPANDED, COMPACT)
fun myScreen_expandedWidthCompactHeight() {
...
}
}
Zmień rozmiar wyświetlaczy
Użyj metody setDisplaySize()
, aby zmienić wymiary ekranu
w czasie działania aplikacji. Używaj tej metody w połączeniu z DisplaySizeRule
dzięki czemu wszystkie zmiany wprowadzone podczas testów są cofnięte przed
następny test.
@RunWith(AndroidJUnit4::class)
class ResizeDisplayTest {
@get:Rule(order = 1) val activityScenarioRule = activityScenarioRule<MainActivity>()
// Test rule for restoring device to its starting display size when a test case finishes.
@get:Rule(order = 2) val displaySizeRule: DisplaySizeRule = DisplaySizeRule()
@Test
fun resizeWindow_compact() {
onDevice().setDisplaySize(
widthSizeClass = WidthSizeClass.COMPACT,
heightSizeClass = HeightSizeClass.COMPACT
)
// Verify visual attributes or state restoration.
}
}
Gdy zmieniasz rozmiar wyświetlacza za pomocą funkcji setDisplaySize()
, nie wpływa to na gęstość
na urządzeniu. Jeśli więc wymiar nie pasuje do urządzenia docelowego, test jest przeprowadzany
kończy się niepowodzeniem na UnsupportedDeviceOperationException
. Aby uniemożliwić przeprowadzanie testów
w tym przypadku, użyj adnotacji RequiresDisplay
, aby je odfiltrować:
@RunWith(AndroidJUnit4::class)
class ResizeDisplayTest {
@get:Rule(order = 1) var activityScenarioRule = activityScenarioRule<MainActivity>()
// Test rule for restoring device to its starting display size when a test case finishes.
@get:Rule(order = 2) var displaySizeRule: DisplaySizeRule = DisplaySizeRule()
/**
* Setting the display size to EXPANDED would fail in small devices, so the [RequiresDisplay]
* annotation prevents this test from being run on devices outside the EXPANDED buckets.
*/
@RequiresDisplay(
widthSizeClass = WidthSizeClassEnum.EXPANDED,
heightSizeClass = HeightSizeClassEnum.EXPANDED
)
@Test
fun resizeWindow_expanded() {
onDevice().setDisplaySize(
widthSizeClass = WidthSizeClass.EXPANDED,
heightSizeClass = HeightSizeClass.EXPANDED
)
// Verify visual attributes or state restoration.
}
}
Tester przywrócenia stanu
Klasa StateRestorationTester
jest używana do testowania przywracania stanu
dla komponentów kompozycyjnych bez odtwarzania działań. To przyspiesza przeprowadzanie testów
i bardziej niezawodne, ponieważ rekreacja to złożony proces
mechanizmy synchronizacji:
@Test
fun compactDevice_selectedEmailEmailRetained_afterConfigChange() {
val stateRestorationTester = StateRestorationTester(composeTestRule)
// Set content through the StateRestorationTester object.
stateRestorationTester.setContent {
MyApp()
}
// Simulate a config change.
stateRestorationTester.emulateSavedInstanceStateRestore()
}
Biblioteka testów okien
Biblioteka Window Testing zawiera narzędzia pomocne w pisaniu testów włączanie i weryfikowanie funkcji związanych z zarządzaniem oknami, takich jak aktywność w dodatku i funkcjach składanych. Artefakt jest dostępny w naszej witrynie Repozytorium Maven.
Możesz na przykład użyć funkcji FoldingFeature()
do wygenerowania
niestandardowy FoldingFeature
, którego można używać w podglądach tworzenia wiadomości. W Javie
użyj funkcji createFoldingFeature()
.
W podglądzie tworzenia wiadomości możesz zaimplementować FoldingFeature
w taki sposób:
@Preview(showBackground = true, widthDp = 480, heightDp = 480)
@Composable private fun FoldablePreview() =
MyApplicationTheme {
ExampleScreen(
displayFeatures = listOf(FoldingFeature(Rect(0, 240, 480, 240)))
)
}
W testach interfejsu możesz też emulować funkcje displayowe za pomocą interfejsu
TestWindowLayoutInfo()
.
W poniższym przykładzie symulowane jest FoldingFeature
z
HALF_OPENED
.
pionowy zawias na środku ekranu, a następnie sprawdza, czy
zgodnie z oczekiwaniami:
Compose
import androidx.window.layout.FoldingFeature.Orientation.Companion.VERTICAL
import androidx.window.layout.FoldingFeature.State.Companion.HALF_OPENED
import androidx.window.testing.layout.FoldingFeature
import androidx.window.testing.layout.TestWindowLayoutInfo
import androidx.window.testing.layout.WindowLayoutInfoPublisherRule
@RunWith(AndroidJUnit4::class)
class MediaControlsFoldingFeatureTest {
@get:Rule(order=1)
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@get:Rule(order=2)
val windowLayoutInfoPublisherRule = WindowLayoutInfoPublisherRule()
@Test
fun foldedWithHinge_foldableUiDisplayed() {
composeTestRule.setContent {
MediaPlayerScreen()
}
val hinge = FoldingFeature(
activity = composeTestRule.activity,
state = HALF_OPENED,
orientation = VERTICAL,
size = 2
)
val expected = TestWindowLayoutInfo(listOf(hinge))
windowLayoutInfoPublisherRule.overrideWindowLayoutInfo(expected)
composeTestRule.waitForIdle()
// Verify that the folding feature is detected and media controls shown.
composeTestRule.onNodeWithTag("MEDIA_CONTROLS").assertExists()
}
}
Wyświetlenia
import androidx.window.layout.FoldingFeature.Orientation
import androidx.window.layout.FoldingFeature.State
import androidx.window.testing.layout.FoldingFeature
import androidx.window.testing.layout.TestWindowLayoutInfo
import androidx.window.testing.layout.WindowLayoutInfoPublisherRule
@RunWith(AndroidJUnit4::class)
class MediaControlsFoldingFeatureTest {
@get:Rule(order=1)
val activityRule = ActivityScenarioRule(MediaPlayerActivity::class.java)
@get:Rule(order=2)
val windowLayoutInfoPublisherRule = WindowLayoutInfoPublisherRule()
@Test
fun foldedWithHinge_foldableUiDisplayed() {
activityRule.scenario.onActivity { activity ->
val feature = FoldingFeature(
activity = activity,
state = State.HALF_OPENED,
orientation = Orientation.VERTICAL)
val expected = TestWindowLayoutInfo(listOf(feature))
windowLayoutInfoPublisherRule.overrideWindowLayoutInfo(expected)
}
// Verify that the folding feature is detected and media controls shown.
onView(withId(R.id.media_controls)).check(matches(isDisplayed()))
}
}
Więcej przykładów znajdziesz w projekcie WindowManager.
Dodatkowe materiały
Dokumentacja
- Wskazówki dotyczące jakości aplikacji na duży ekran
- Testowanie aplikacji na Androidzie
- Testowanie układu tworzenia wiadomości
Próbki
- Przykład elementu WindowManager
- Próbki urządzeń do espresso
- Teraz na Androidzie
- Przeprowadza testy zrzutów ekranu, aby sprawdzić różne rozmiary ekranów
Ćwiczenia z programowania