UI тестирање проверава исправност приказивања и интеракције елемената корисничког интерфејса мобилне апликације — дугмића, текстуалних поља, листи и навигационих компонената. За разлику од јединичних тестова који проверавају пословну логику, UI тестови емулирају акције корисника: додире, превлачења, унос текста и проверавају реакцију интерфејса. Према истраживању Android Developers, 2024, UI тестирање покрива 70% критичних корисничких сценарија и омогућуће откривање дефеката распореда који нису доступни за логичке провере.
Главно
UI тестирање је врста аутоматизоване провере у којој тестни код интерагује са графичким интерфејсом апликације исто као што би то радио реалан корисник. Тест проналази на екрану елеменат — дугме, текстуално поље, листу — извршава акцију на њему и проверава очекивану реакцију интерфејса. На пример, након уношења неисправне лозинке, UI тест проверава да ли се на екрану појавила порука о грешци са исправним текстом.
Главна разлика између UI тестова и других врста аутоматизације је што они раде кроз асесибилност слој оперативног система, а не кроз унутрашњи API апликације. То значи да UI тестови виде интерфејс потпуно исто као корисник и систем за читање екрана. Захваљујући томе, UI тестови проверавају не само функционалност, већ и приступачност елемената — усаглашеност са WCAG захтевима.
Према истраживању JetBrains Developer Ecosystem 2023, 58% мобилних тимова користи UI тестове у свом CI/CD пајплајну. Просечно покривање UI тестовима у комерцијалним пројектима износи 30–40% екрана апликације. Пројекти са UI тестовима 25% ређе добијају негативне оцене у продавницама апликација везане за падове интерфејса.
Главна разлика између UI тестова и јединичних тестова је ниво апстракције. Јединични тестови раде са појединачним класама и функцијама, изолованим од Android или iOS оквира. Извршавају се на JVM (за Android) без покретања емулатора и трају милисекунде. UI тестови се покрећу на реалном уређају или емулатору, интерагују са системским услугама и захтевају секунде или минуте за један сценариј.
Разликује се и циљна публика тестова. UI тестови проверавају целовите корисничке сценарије — регистрацију, поручивање, претрагу. Јединични тестови покривају пословну логику: прорачуне, валидацију, трансформацију података. UI тест не проверава исправност обрачуна пореза — он проверава да ли се коначни износ приказује на екрану. Сам обрачун се проверава јединичним тестом.
Према Google Testing Blog (2020), оптимални однос тестова у пројекту треба да прати правило пирамиде тестирања: 70% јединичних тестова, 20% интеграционих и 10% UI тестова. Кршење овог односа у корист UI тестова доводи до повећања времена извршења и крхкости тестног скупа, јер су UI тестови осетљиви на промене у распореду екрана.
За Android доминантни оквир је Espresso — библиотека од Google уграђена у AndroidX Test. Espresso се аутоматски синхронизује са UI нити, чекајући завршетак анимација и позадинских задатака пре него што изврши следећу проверу. За Jetpack Compose користи се проширење Compose UI Test, које ради кроз семантичке чворове уместо традиционалних идентификатора приказа.
За iOS главни алат је XCUITest, који је саставни део Xcode. Тестови се пишу на Swift-у и користе Accessibility идентификаторе за проналажење елемената. XCUITest подржава снимање тестова кроз record функцију и интеграцију са CI системима кроз xcodebuild. За вишеплатформне пројекте примењује се Appium, заснован на WebDriver протоколу, који омогућуће покретање истих тестова на Android и iOS са минималним изменама у коду.
Espresso ради са традиционалним View системом кроз onView и id идентификаторе ресурса. Compose UI Test користи семантички слој, што чини тестове мање зависним од хијерархије приказа. На пример, проналажење дугмета у Espresso: onView(withId(R.id.submit)), у Compose: onNodeWithTag(„submit”). Compose тестови аутоматски обрађају рекомпозицију и не захтевају експлицитно чекање на стање мировања.
XCUITest користи XCUIApplication као улазну тачку. Сваки елеменат интерфејса се проналази кроз Accessibility својства: accessibilityIdentifier за програмски приступ и accessibilityLabel за VoiceOver. Оквир подржава снимање тестова кроз record функцију у Xcode-у — програмер извршава акције на симулатору, а Xcode генерише тестни код. Готови тестови се покрећу кроз xcodebuild test.
Appium је заснован на WebDriver протоколу и подржава било који језик: Java, Python, JavaScript. За проналажење елемената користе се стратегије id, xpath, class name и accessibility id. Appium захтева инсталацију сервера и подешавање Desired Capabilities — platformName, deviceName, appPackage. Алтернатива је Maestro, који користи YAML сценарије и не захтева компилацију тестног кода.
Погледајмо UI тестове за исти сценариј — пријаву на апликацију — у три различита оквира: Espresso за Android, XCUITest за iOS и Appium за вишеплатформни приступ. Сценариј: унесите корисничко име и лозинку, притисните дугме за пријаву, проверите приказ поруке добродошлице.
Тест у Espresso користи onView за проналажење елемента по идентификатору и perform за извршавање акције. Метода check са matcher-ом isDisplayed потврђује да је елеменат видљив на екрану.
@RunWith(AndroidJUnit4::class)
class LoginUiTest {
@Rule
@JvmField
val composeTestRule = createComposeRule()
@Test
fun login_withValidCredentials_showsWelcome() {
composeTestRule
.onNodeWithTag("emailField")
.performTextInput("user@example.com")
composeTestRule
.onNodeWithTag("passwordField")
.performTextInput("secret123")
composeTestRule
.onNodeWithTag("loginButton")
.performClick()
composeTestRule
.onNodeWithText("Добро дошли, Корисниче!")
.assertIsDisplayed()
}
}
XCUITest користи XCUIApplication за приступ елементима интерфејса кроз Accessibility идентификаторе. Методе tap() и exists омогућују интеракцију и проверу.
class LoginUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
continueAfterFailure = false
app.launch()
}
func testLogin_withValidCredentials_showsWelcome() {
app.textFields["emailField"].tap()
app.textFields["emailField"].typeText("korisnik@example.com")
app.secureTextFields["passwordField"].tap()
app.secureTextFields["passwordField"].typeText("tajna123")
app.buttons["loginButton"].tap()
XCTAssertTrue(app.staticTexts["Welcome, User!"].exists)
}
}
Први принцип — користите Accessibility идентификаторе уместо текстуалних ознака за проналажење елемената. Текст дугмета се може променити при локализацији, а идентификатор ће остати стабалан. У Android-у је то својство contentDescription, у iOS-у — accessibilityIdentifier. Овакав приступ чини тестове независним од језика интерфејса и смањује трошкове одржавања при промени копирајтинга.
Избегавајте sleep() и фиксних кашњења — користите уграђене механизме чекања оквира. Espresso аутоматски чека завршетак анимација и позадинских задатака. XCUITest пружа XCTAssertTrue са timeout-ом. Експлицитне паузе успоравају тестове и чине их мање стабилним, посебно на спорим уређајима у CI окружењу.
Групишите тестове по критичности: smoke тестови (3–5 кључних сценарија) покрећу се на сваки комит, пун сет UI тестова — пре издавања. Према Google Testing Blog (2022), UI тестови који трају дуже од 30 минута у CI-ју смањују учесталост покретања за 40%, што смањује њихову ефикасност као алата за рано откривање регресија.
UI тестови имају низ ограничења. Осетљивост на промене распореда: промена идентификатора, хијерархије или типа елемента квари тест чак и са непромењеном функционалношћу. Решење — коришћење Page Object обрасца, који централизује селекторе елемената у одвојене класе. При промени распореда прави се један фајл Page Object, а не десетине тестова.
Време извршења: покретање на реалном уређају или емулатору траје 10–50 пута дуже од јединичног теста. Решење — паралелно покретање UI тестова на више уређаја кроз Firebase Test Lab или AWS Device Farm. Нестабилност (flakiness) — чест проблем CI покретања, изазван анимацијама, мрежним кашњењима или стањем емулатора. За борбу са flakiness примењују се аутоматско понављање палих тестова и анализа стабилности сваког тестног сценарија.
Често постављана питања
За просечан екран довољно је 3–5 UI тестова: happy path, валидација грешака, празно стање, промена оријентације и Accessibility провера. Сложени екрани са више стања — формулари за поручивање, подешавања — могу захтевати 10–15 тестова за потпуно покривање кључних сценарија.
Да, Appium и Maestro омогућућу покретање истих сценарија на обе платформе. Међутим, нативни оквири — Espresso и XCUITest — пружају бољу стабилност, брзину и приступ могућностима платформе који нису доступни кроз WebDriver прокси.
За Compose се користи библиотека Compose UI Test са семантичким matcher-има: onNodeWithText, onNodeWithTag, onNodeWithContentDescription. Семантички слој у Compose-у апстрахира хијерархију приказа, што чини тестове мање крхким у поређењу са традиционалним Espresso за View систем.
Базно покретање UI тестова обавља се на емулаторима у CI-ју — брзо је и јефтино. Коначну верификацију пре издавања препоручује се обављати на физичким уређајима кроз Firebase Test Lab да би се узеле у обзир карактеристике реалног хардвера: различите резолуције, верзије оперативног система и перформансе.
Користите паралелно покретање на више уређаја, искључите анимације на емулатору кроз Developer Options, изградите модулну архитектуру тестова и покрећите smoke сет на сваки комит, а пуни регресиони прогон — по распореду или пре издавања.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође