你好。我们在Avokado项目上继续谈论Android的自动测试。本文概述和比较了用于编写UI测试的现有工具。
让我们从记住测试过程通常的样子开始。让我们将与应用程序交互的实体称为客户端。为了与应用程序交互,客户端通常具有多个可用接口:API,REST API,CLI,GUI等。并且,例如,如果客户端程序使用了API,那么人类将使用GUI。
规范中描述了对应用程序行为的期望。测试的目的是验证应用程序的行为是否符合规范。
为了解决此问题,记录了一组用例或测试用例。它们是使产品达到所需状态的步骤序列。因此,测试应用程序的过程就是通过所有测试用例的过程。
- . , . -.
(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- , . ( . , ). , . . , .
. , , , . , , 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")
. Localization autotests.
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 | + | − | − | + |