ํ์ ํ๋ ๊ฐ๋ฐ์๋ค ๋ผ๋ฆฌ ์๋ก์ ์ฝ๋๋ฅผ ๋ค ์ดํด๋ณผ ์ ์์ต๋๋ค. ํนํ, ๊ฐ์ ๊ฐ๋ฐํ UI์ ๋ํด ํ๋์ ์์๋ณด๋ ๊ฒ์ ๋์ฑ ํ๋ ์ผ์ ๋๋ค.
UI Test๋ฅผ ์์ฑํ๋ ๊ฒ ๋ง์ผ๋ก๋ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ ์ถ๊ฐ ๊ฐ๋ฅํ๊ฒ ๋๊ณ , ์ด๊ฒ์ ์ผ์ข ์ ๋ฌธ์ ์ญํ ์ ํ๊ฒ ๋ฉ๋๋ค.
ํ๋ก์ ํธ ๋ํค(Duckie)๋ ๋ ๋ฆฝ์ ์ธ ๋์์ธ ์์คํ (Quack-Quack)์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ํค์ ๊ฑฐ์ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ๋์์ธ ์์คํ ์ ์ปดํฌ๋ํธ๋ก ์ด๋ฃจ์ด์ง ๊ฒ์ด๋ฏ๋ก ์ค์์ฑ์ ์ด๋ฃจ ๋งํ ์๊ฐ ์์ต๋๋ค. ๋ฐ๋ผ์ UI Test๋ฅผ ํตํด UI๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ๊ฒ์ฆํ๊ณ , ์์ ์ฑ์ ๊ฒ์ฆํ๋ ๊ณผ์ ์ ํ์๋ก ๊ฑฐ์น๊ฒ ๋์์ต๋๋ค.
https://github.com/sungbinland/duckie-quack-quack
UI Tree์ ์๋ฏธ๋ก ์ ์ธ ์์๋ฅผ ๋ถ์ฌํ ์ฒด๊ณ ๋ผ๊ณ ํ ์ ์์ต๋๋ค
.View System์์๋, ๊ฐ View๊ฐ ๊ณ์ธต ๊ตฌ์กฐ ๋ด์ ์ ์๋๊ณ , ๊ด๋ จ ์์ฑ์ ๋ณด์ ํ ์ ์์์ต๋๋ค.
์ปดํฌ์ ๋ธ๊ฐ์ ๊ฒฝ์ฐ ์๊ฐ์ ํํ์ ์ค์ ์ ๋๋ background๋ผ๋์ง, text๋ผ๋์ง ์์ ์ปจํ ์ด๋์ ์ ๋ ฌ์ ํฌํจํ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ฐฉ์ถํฉ๋๋ค.ย
์ด๋ฌํ ์๋ฏธ์์ Semantic์ ๋ฐฉ์ถ๋ ์์ ์ ์ปดํฌ์ ๋ธ์ ์๋ฏธ๋ฅผ ๋ถ์ฌํ๊ณ ์ฐพ๊ธฐ ์ํ ์์คํ
์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค.
Compose์ UI ํ ์คํธ๋ Semantic์ ์ฌ์ฉํ์ฌ UI ๊ณ์ธต ๊ตฌ์กฐ์ ์ํธ์์ฉ ํ๊ฒ ๋ฉ๋๋ค. Semantic tree๋ UI ๊ณ์ธต ๊ตฌ์กฐ์ ํจ๊ป ์์ฑ๋๊ณ UI ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํ์ฑํฉ๋๋ค
๊ฐ๊ฐ์ UI์์์ ์๋งจํฑ์ด ์๋ฏธ๋ฅผ ๋ถ์ฌํ๊ฒ ๋๋๋ฐ, ์ด ์๋ฏธ๋ผ๋ ๊ฒ์ Test FrameWork์์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ์์ ๋งํฉ๋๋ค. ์ฆ, composeTestRule.*onNodeWithText(text)
๊ฐ์ ๋ฐฉ์์ผ๋ก Semantic Node์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ์์ ๋งํฉ๋๋ค.*
junit4
ํ๊ฒฝ์์ ๊ฐ๋จํ ๋ฒํผ ํ
์คํธ๋ฅผ ์งํํ๋ฉด์ ํ
์คํธ์ ํ๋ฆ์ ์ง์ด๋ณด๊ฒ ์ต๋๋ค.
ComposeTestRule์ component, Activity๋ฅผ ์์ํ๋ ๋ฐฉ๋ฒ ๋ฐ finder, actions, assertions ๋ฑ์ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค์
๋๋ค.
ํน์ ์กํฐ๋นํฐ๋ฅผ ์ง์ ํ๊ณ ์ถ๋ค๋ฉด createAndroidComposeRule<ACTIVITY_NAME>() ์ ํตํด ์์ฑํ ์ ์์ต๋๋ค.
@get:Rule
val composeTestRule = createComposeRule()
๋ํค ๋์์ธ ์์คํ (Quack-Quack) ์์๋ ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธ ํด์ผํ๋ฏ๋ก, createComposeRule()์ ์์ฑํ์ฌ ๋ ธ๋๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค.
Semantic Node๋ฅผ ์๋ณํ๊ธฐ ์ํด, Companion Object์ ์ ์ธํ TEST_TAG๋ฅผ ์ง์ ํด ์ค๋๋ค.
composeTestRule.setContent{
Button(onClick = { }) {
Text(TEST_TAG)
}
}
Semantic์ UI ์์์ ์๋ฏธ๋ฅผ ๋ถ์ฌํ๋ค๊ณ ํ์ต๋๋ค.
Finder๋, ์ฃผ์ด์ง ์ด๋ ํ ์กฐ๊ฑด์ ํตํด ์๋ฏธ๊ฐ ๋ถ์ฌ๋ ๋ ธ๋๋ฅผ ์ฐพ์ ์ ์๊ฒ ํด์ค๋๋ค.
์๋ฅผ๋ค์ด, argument๋ก ์ฃผ์ด์ง Text๋ฅผ ๊ฐ์ง๊ณ ์๋ Semantic Node๋ฅผ ์ฐพ์ผ๋ ค๋ฉด
composeTestRule.onNodeWithText(TEST_TAG)
๋ฅผ ํธ์ถํ๋ฉด ๋ฉ๋๋ค.
ํด๋น ๋ฉ์๋๋ SemanticsNodeInteraction
๋ฅผ ๋ฐํํ๊ณ , ์ฐพ์ ๋
ธ๋์ ๋ํ Interaction
์ ์งํํ ์ ์์ต๋๋ค.
ํน์ onAllNodes
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๋
ธ๋๋ฅผ ์ ํํ ์๋ ์์ต๋๋ค.
ํน์ ์์๊ฐ ์๋์ง, ํ๋ฉด์ ๋ํ๋ฌ๋์ง ๋ฑ์ ๋ํ ์ํ๋ฅผ ํ์ธํฉ๋๋ค.
composeTestRule.onNodeWithText(TEST_TAG).assertIsDisplayed()
์ด์ฒ๋ผ Finder, Assertion, Action์ ์ ์ ํ ํ์ฉํ์ฌ ์์๋ฅผ ์ฐพ์ ์์ฑ์ ํ์ธํ๊ณ Interaction์ ์คํํ๋ ํ ์คํธ๋ฅผ ์์ฑํ๋ฉด ๋ฉ๋๋ค.
https://developer.android.com/jetpack/compose/semantics?hl=ko
https://developer.android.com/jetpack/compose/testing?hl=ko
https://joebirch.co/android/jetpack-compose-accessibility-semantics/
์ฌ๊ธฐ ๋ง์ง์ด๋ค.