Hola. En el Proyecto Avokado seguimos hablando sobre pruebas automáticas en Android. Este artículo es una descripción general y una comparación de las herramientas existentes para escribir pruebas de IU.
Comencemos recordando cómo suele ser el proceso de prueba. Llamemos cliente a la entidad que interactúa con la aplicación. Para interactuar con la aplicación, el cliente suele tener varias interfaces disponibles: API, API REST, CLI, GUI, etc. Y si, por ejemplo, los programas cliente utilizan las API, los humanos utilizan la GUI.
Las expectativas del comportamiento de la aplicación se describen en la especificación. El objetivo de las pruebas es verificar que el comportamiento de la aplicación se ajuste a la especificación.
Para resolver este problema, se registra un conjunto de casos de uso o casos de prueba. Son secuencias de pasos que llevan el producto al estado deseado. Por lo tanto, el proceso de probar una aplicación es el proceso de aprobar todos los casos de prueba.
- . , . -.
(JUnit, Cucumber). :
- — (assertions).
- . — , .
- .
:
- ;
- ;
- ;
- ;
- ;
- .
, , . , Android-, (Avito test runner, Marathon, Spoon, Fork) , .
API , GUI — .
, GUI-, UI-. unit-, .
GUI- . , . GUI- (Espresso, UiAutomator) « », , , .
API :
- : , , , .
- API .
- .
, , Kakao Kaspresso. . — , — , .
, .
Android- :
- Espresso.
- UiAutomator.
- Robotium.
- Selendroid.
Android Instrumentation Framework — API Android . — Espresso UiAutomator. Google. . .
UiAutomator
UiAutomator Android SDK 16 API. GUI- : , , , , . , — Ui Automator Viewer.
UiAutomator (black-box). . , , . , , :
- ;
- ;
- ;
- , ;
- .
UiAutomator AccessibilityService
, . AccessibilityService
, . , AccessibilityNodeInfo
. View: , .
View AccessibilityEventSource
Binder IPC AccessibilityManagerService
, , , . AccessibilityManagerService
AccessibilityService
, , UiAutomator, . AccessibilityService’
UiAutomator’a . View
, .
UiAutomator “UI Automator deep diving”.
UiAutomator:
- , Binder IPC, . , UiAutomator , . , . , .
- ,
View
OpenGL Unity, UiAutomator’a, . , , UiAutomator’a .
, UiAutomator , . Espresso.
Espresso
UI- Google, (white-box). Espresso Android API 10 , . .
Espresso . , .
Espresso — (ViewMatcher
), (ViewAction
) (ViewAssertion
).
Espresso Hamcrest. — , , Espresso — . , , . , .
@Test
public void espressoTest() {
onView(allOf(allOf(withId(R.id.label_bf_hotelname),
isDescendantOfA(withId(R.id.custom_view_trip_review))),
isDescendantOfA(withId(R.id.contentView))))
.check(matches(
withEffectiveVisibility(Visibility.VISIBLE)
));
}
Espresso — Espresso , . . , (idle).
, , , , check
ViewInteraction
. ViewAssertion
idle’.
public ViewInteraction check(ViewAssertion viewAssertion) {
// (...)
runSynchronouslyOnUiThread(new Callable<Void>() {
@Override
public Void call() {
uiController.loopMainThreadUntilIdle();
// (...)
viewAssertion.check(...)
}
});
}
Espresso:
- .
- . , , . Espresso . UiAutomator.
- API Espresso , . .
- Espresso .
, , Espresso — , .
Robotium Selendroid
Robotium Selendroid Espresso UiAutomator. C , . , .
Robotium Android API 8+, ( WebView , , API 15), Java. Robotium Recorder IntelliJ IDEA Android Studio.
Selendroid API — 10 19. WebDriver, Inspector record-and-playback-.
, Robotium Selendroid.
Robolectric
, Robolectric , . , Android UI-. Robolectric unit- JUnit Android API.
Android SDK, shadow-. Robolectric , inflate view, , , - Android-. Robolectric , Android, , JVM. , .
, . , : - . - API, . , . , , , Espresso UiAutomator.
. API , .
, , .
. UI- , . ( . , ). , . . , .
. , , . black-box . . , , black-box , , . white-box, black-box .
. , . , . , , .
. , . : , , , — , , . , , , , . stacktrace’ , , , , .
. . , . , .
adb. adb: / , , .
API. — , . , , , — , . , , . , .
.
Appium
Appium — - open source Android iOS. Appium Selenium WebDriver, web-. . Appium- , . Appium API.
. , Appium . HTTP- Node.JS, WebDriver-, . , , . , , Appium .
. Appium , . Android UiAutomator, Espresso. , , . . Espresso UiAutomator.
API. Appium API, WebDriver. Appium , .
. , , , , ( ), Appium-, , , , . , . — .
. , .
. , .
adb. - Appium’ , adb-. , , .
. Appium . — Espresso . - , .
, Appium — Android- . , Kotlin, Java. - Appium . , . : « . , , », « ».
Kakao
Kakao — Kotlin DSL Espresso. Espresso .
API. Kakao — boilerplate- :
KView
— Kakao- , . , Kakao ,KEditText
,KButton
.. .Screen
— - PageObject.Screen
— , stateless-KView
.Screen
, , , .Screen’
, .
, , Espresso. :
@Test
public void espressoTest() {
onView(allOf(allOf(withId(R.id.label_bf_hotelname),
isDescendantOfA(withId(R.id.custom_view_trip_review))),
isDescendantOfA(withId(R.id.contentView))))
.check(matches(
withEffectiveVisibility(Visibility.VISIBLE)
));
}
:
object MainScreen : Screen<MainScreen>() {
val hotelName = KTextView { withId(R.id.label_bf_hotelname) }
}
@Test
fun kakaoTest() {
MainScreen {
hotelName {
isVisible()
}
}
}
. Kakao — , Appium, . - . Espresso , , — , ..
. Kakao Espresso, .
. Kakao . API , Espresso-. , , . - - .
. , Espresso. .
. . .
adb. , Espresso.
. , Kakao — DSL Espresso. UiAutomator, API . , , .
Barista
Barista — , Espresso.
API. Kakao, Espresso. Barista — , Espresso-. :
- helper- , Espresso . ,
onView(withId(R.id.button)).perform(click())
EspressoclickOn(R.id.button)
.clickListItem(R.id.list, 4)
. - Android- Assertions API.
- , .
- runtime permission’.
- test rule’, , flaky- shared preferences, , .
Barista NestedScrollView, Espresso, . DSL , .
. FlakyTestRule . . , .
. - Espresso.
. , Espresso . Espresso.
. , .
. .
adb. , Espresso.
. Barista . , , . .
Kaspresso
- UI-, , .
API. Kakao. Kaspresso Kakao DSL — Kotlin DSL , Kakao Screen’
KView
.
@RunWith(AndroidJUnit4::class)
class OpenHomeScreenTest : TestCase() {
@Test
fun kaspressoTest() {
before { ... }
.after { ... }
.run {
step("1. Open Home screen") {
MainScreen {
openHomeScreenBtn.click()
}
}
step("2. Check Home title") {
HomeScreen {
title.isVisible()
}
}
step("3. Do some stuff") { ... }
}
}
}
Kaspresso API , . , (. How to write autotests).
. Kaspresso - API Espresso UiAutomator. , , , . , , . Kaspresso Kautomator — Kakao-like UiAutomator, Espresso UiAutomator .
object KakaoScreen : Screen<KakaoScreen>() {
val title = KTextView { withText(titleText) }
val btn = KButton { withId(R.id.button1) }
}
object KautomatorScreen : UiScreen<KautomatorScreen>() {
val title = UiTextView { withText(titleText) }
val btn = UiButton { withId(pkgName, R.id.button2) }
}
@Test
fun kaspressoTest() {
KakaoScreen {
title.isVisible()
btn.click()
}
KautomatorScreen {
title.isVisible()
btn.click()
}
}
device. , :
- ;
- ;
- ;
- , , ;
- ;
- ;
- ;
- : back, home, recents.
Kaspresso , .
. Kaspresso , . , , ViewAction
ViewAssertion
, , . , , , (. Configurator).
. Kaspresso Espresso UiAutomator , , ScrollView
, , . helper-. , flakySafely
:
MainScreen {
flakySafely {
btn.click()
}
}
. , , .
. . , Kaspresso , . :
device.screenshots.take("MainScreen_step_1")
adb. Kaspresso AdbServer — HTTP-, adb-. , , . , adb- . AdbServer , device. API adb-:
adbServer.performAdb("emu sms send +79111111111 $smsText")
adbServer.perfromShell("rm -f $filePath")
AdbServer , , adb.
Appium | Kakao | Barista | Kaspresso | |
API | − | + | ± | + |
+ | − | − | + | |
− | + | − | + | |
− | ± | ± | + | |
− | ± | − | + | |
− | − | − | + | |
adb | + | − | − | + |