Hallo. Wir vom Avokado-Projekt sprechen weiterhin ĂŒber Autotesting in Android. Dieser Artikel bietet einen Ăberblick und einen Vergleich vorhandener Tools zum Schreiben von UI-Tests.
Lassen Sie uns zunĂ€chst daran erinnern, wie der Testprozess normalerweise aussieht. Nennen wir die EntitĂ€t, die mit der Anwendung interagiert, einen Client. FĂŒr die Interaktion mit der Anwendung stehen dem Client normalerweise mehrere Schnittstellen zur VerfĂŒgung: API, REST-API, CLI, GUI usw. Und wenn beispielsweise APIs von Client-Programmen verwendet werden, wird die GUI von Menschen verwendet.
Erwartungen an das Anwendungsverhalten sind in der Spezifikation beschrieben. Ziel des Tests ist es, zu ĂŒberprĂŒfen, ob das Verhalten der Anwendung der Spezifikation entspricht.

Um dieses Problem zu lösen, wird eine Reihe von AnwendungsfĂ€llen oder TestfĂ€llen aufgezeichnet. Es sind Abfolgen von Schritten, die das Produkt in den gewĂŒnschten Zustand bringen. Das Testen einer Anwendung ist somit das Bestehen aller TestfĂ€lle.
- . , . -.
(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 , . , . , .
- ,
ViewOpenGL 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 | + | â | â | + |