Bonjour. Nous au projet Avokado continue Ă parler autotesting dans Android. Cet article est une vue d'ensemble et une comparaison des outils existants pour Ă©crire des tests d'interface utilisateur.
Commençons par rappeler à quoi ressemble habituellement le processus de test. Appelons l'entité qui interagit avec l'application un client. Pour interagir avec l'application, le client dispose généralement de plusieurs interfaces: API, API REST, CLI, GUI, etc. Et si, par exemple, les API sont utilisées par des programmes clients, alors l'interface graphique est utilisée par des humains.
Les attentes concernant le comportement de l'application sont décrites dans la spécification. Le but des tests est de vérifier que le comportement de l'application est conforme à la spécification.
Pour résoudre ce problÚme, un ensemble de cas d'utilisation ou de cas de test est enregistré. Ce sont des séquences d'étapes qui amÚnent le produit à l'état souhaité. Ainsi, le processus de test d'une application est le processus de réussite de tous les cas de test.
- . , . -.
(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 | + | â | â | + |