{"id":45758,"date":"2021-11-23T16:17:27","date_gmt":"2021-11-23T07:17:27","guid":{"rendered":"https:\/\/www.charlezz.com\/?p=45758"},"modified":"2021-11-23T16:17:29","modified_gmt":"2021-11-23T07:17:29","slug":"testing-in-jetpack-compose-%ea%b0%84%eb%8b%a8%ed%95%9c-ui-%ed%85%8c%ec%8a%a4%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/charlezz.com\/?p=45758","title":{"rendered":"Testing in Jetpack Compose &#8211; \uac04\ub2e8\ud55c UI \ud14c\uc2a4\ud2b8 \ub9cc\ub4e4\uae30"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">TopAppBarTest \ud30c\uc77c \uc0dd\uc131\ud558\uae30<\/h2>\n\n\n\n<p>AnimatingCircleTests.kt(app\/src\/androidTest\/com\/example\/compose\/rally)\uc640 \ub3d9\uc77c\ud55c \ud3f4\ub354\uc5d0 \uc0c8 \ud30c\uc77c\uc744 \ub9cc\ub4e4\uace0 TopAppBarTest.kt\ub77c\uace0 \uc774\ub984\uc744 \uc9d3\ub294\ub2e4.<\/p>\n\n\n\n<p>\ucef4\ud3ec\uc988\ub294 createComposeRule()\uc744 \ud638\ucd9c\ud558\uc5ec \uc5bb\uc744 \uc218 \uc788\ub294 ComposeTestRule\uacfc \ud568\uaed8 \uc81c\uacf5\ub41c\ub2e4. \uc774 \uaddc\uce59\uc744 \uc0ac\uc6a9\ud558\uba74 \ud14c\uc2a4\ud2b8 \uc911\uc778 Compose \ucf58\ud150\uce20\ub97c \uc124\uc815\ud558\uace0, \uc0c1\ud638 \uc791\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ComposeTestRule\uc744 \ucd94\uac00\ud558\uae30<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>class TopAppBarTest {\n\n\u00a0 \u00a0 <strong>@get:Rule\n\u00a0 \u00a0 val composeTestRule = createComposeRule()<\/strong>\n\u00a0 \u00a0 \n\u00a0 \u00a0 \/\/ TODO: \ud14c\uc2a4\ud2b8 \ucd94\uac00\ud558\uae30\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uaca9\ub9ac\ub41c \ud14c\uc2a4\ud2b8<\/h2>\n\n\n\n<p>\ucef4\ud3ec\uc988 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub294 \uc608\ub97c \ub4e4\uc5b4 Espresso\ub97c \uc0ac\uc6a9\ud558\uc5ec Android View \uc5d0\uc11c \uc218\ud589\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c \uc571\uc758 \uba54\uc778 \uc561\ud2f0\ube44\ud2f0\ub97c \uc2dc\uc791\ud560 \uc218 \uc788\ub2e4. createAndroidComposeRule\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc774 \uc791\uc5c5\uc744 \uc218\ud589\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \uc774 \ucf54\ub4dc\ub97c \ubcf5\uc0ac\ud558\uc9c0 \ub9d0\uc790.\n\n@get:Rule\nval composeTestRule = <strong>createAndroidComposeRule(RallyActivity::class.java)<\/strong><\/code><\/pre>\n\n\n\n<p>\uadf8\ub7ec\ub098 \ucef4\ud3ec\uc988\ub97c \uc0ac\uc6a9\ud558\uba74 \uaca9\ub9ac\ub41c \ucef4\ud3ec\ub10c\ud2b8\ub97c \ud14c\uc2a4\ud2b8\ud558\uc5ec \uc791\uc5c5\uc744 \uc0c1\ub2f9\ud788 \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4. \ud14c\uc2a4\ud2b8\uc5d0 \uc0ac\uc6a9\ud560 \ucef4\ud3ec\uc988 UI \ucf58\ud150\uce20\ub97c \uc120\ud0dd\ud560 \uc218 \uc788\ub2e4. \uc774\uac83\uc740 ComposeTestRule\uc758 setContent \uba54\uc18c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc218\ud589\ub418\uba70, \uc5b4\ub514\uc5d0\uc11c\ub098 \ud638\ucd9c\ud560 \uc218 \uc788\ub2e4(\ub2e8 \ud55c \ubc88\ub9cc).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \uc774 \ucf54\ub4dc\ub97c \ubcf5\uc0ac\ud558\uc9c0 \ub9d0\uc790.\n\nclass TopAppBarTest {\n\n\u00a0 \u00a0 @get:Rule\n\u00a0 \u00a0 val composeTestRule = createComposeRule()\n\u00a0 \u00a0 \n\u00a0 \u00a0 <strong>@Test\n\u00a0 \u00a0 fun myTest() {\n\u00a0 \u00a0 \u00a0 \u00a0 composeTestRule.setContent { \n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Text(\"You can set any Compose content!\")\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 }<\/strong>\n}<\/code><\/pre>\n\n\n\n<p>\uc6b0\ub9ac\ub294 TopAppBar\ub97c \ud14c\uc2a4\ud2b8\ud558\uace0 \uc2f6\uc73c\ubbc0\ub85c, \uadf8\uac83\uc5d0 \uc9d1\uc911\ud558\ub3c4\ub85d \ud558\uc790. setContent \ub0b4\uc5d0\uc11c RallyTopAppBar\ub97c \ud638\ucd9c\ud558\uace0, Android Studio\uac00 \ub9e4\uac1c\ubcc0\uc218 \uc774\ub984\uc744 \uc644\uc131\ud558\ub3c4\ub85d \ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class TopAppBarTest {\n\n\u00a0 \u00a0 @get:Rule\n\u00a0 \u00a0 val composeTestRule = createComposeRule()\n\u00a0 \u00a0 \n\u00a0 \u00a0 <strong>@Test\n\u00a0 \u00a0 fun rallyTopAppBarTest() {\n\u00a0 \u00a0 \u00a0 \u00a0 composeTestRule.setContent { \n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RallyTopAppBar(\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 allScreens = ,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 onTabSelected = { \/*TODO*\/ },\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 currentScreen = \n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 )\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 }<\/strong>\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\ud14c\uc2a4\ud2b8 \uac00\ub2a5\ud55c \ucef4\ud3ec\uc800\ube14\uc758 \uc911\uc694\uc131<\/h2>\n\n\n\n<p>RallyTopApBar\ub294 \uc6b0\ub9ac\uac00 \uc81c\uc5b4\ud558\ub294 \u200b\u200b\uac00\uc9dc \ub370\uc774\ud130\ub97c \uc804\ub2ec\ud560 \uc218 \uc788\ub3c4\ub85d, \uc81c\uacf5\ud558\uae30 \uc26c\uc6b4 \uc138 \uac00\uc9c0 \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    @Test\n\u00a0 \u00a0 fun rallyTopAppBarTest() {\n\u00a0 \u00a0 \u00a0 \u00a0 <strong>val allScreens = RallyScreen.values().toList()<\/strong>\n\u00a0 \u00a0 \u00a0 \u00a0 composeTestRule.setContent { \n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RallyTopAppBar(\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 allScreens = <strong>allScreens<\/strong>,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 onTabSelected = { },\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 currentScreen = RallyScreen.Accounts\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 )\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 \u00a0 \u00a0 <strong>Thread.sleep(5000)<\/strong>\n\u00a0 \u00a0 }<\/code><\/pre>\n\n\n\n<p>\uc6b0\ub9ac\ub294 \ub610\ud55c \uc5b4\ub5a4\uc77c\uc774 \uc77c\uc5b4\ub098\uace0 \uc788\ub294\uc9c0 \ubcfc \uc218 \uc788\ub3c4\ub85d sleep()\uc744 \ucd94\uac00\ud55c\ub2e4. rallyTopAppBarTest\ub97c \ub9c8\uc6b0\uc2a4 \uc624\ub978\ucabd \ubc84\ud2bc\uc73c\ub85c \ud074\ub9ad\ud558\uace0 &#8220;Run RallyTopAppBarTest()&#8230;&#8220;&#8221;\uc744 \ud074\ub9ad\ud55c\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-testing\/img\/baca545ddc8c3fa9.png?hl=ko\" alt=\"baca545ddc8c3fa9.png\" width=\"450\" height=\"800\"\/><\/figure><\/div>\n\n\n\n<p>\ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0c1\ub2e8 \uc571 \ubc14(5\ucd08 \ub3d9\uc548)\uac00 \ud45c\uc2dc\ub418\uc9c0\ub9cc \uc608\uc0c1\ub300\ub85c \ubcf4\uc774\uc9c0 \uc54a\ub294\ub2e4. \uc571\ubc14\ub294 \ub77c\uc774\ud2b8 \ud14c\ub9c8\ub97c \uac16\uace0 \uc788\ub2e4.<\/p>\n\n\n\n<p>\uadf8 \uc774\uc720\ub294 \ubc14(bar)\uac00 MaterialTheme \ub0b4\uc5d0 \uc788\uc744 \uac83\uc73c\ub85c \uc608\uc0c1\ub418\ub294, Material Components\ub97c \uc0ac\uc6a9\ud558\uc5ec \uad6c\ucd95\ub418\uae30 \ub54c\ubb38\uc774\ub2e4. \uadf8\ub807\uc9c0 \uc54a\uc73c\uba74 &#8220;baseline&#8221; \uc2a4\ud0c0\uc77c \uc0c9\uc0c1\uc73c\ub85c \ub300\uccb4\ub41c\ub2e4.<\/p>\n\n\n\n<p>Materialtheme\uc5d0\ub294 \uc88b\uc740 \uae30\ubcf8\uac12\uc774 \uc788\uc73c\ubbc0\ub85c \ucda9\ub3cc\ub418\uc9c0 \uc54a\ub294\ub2e4. \ud14c\ub9c8\ub97c \ud14c\uc2a4\ud2b8\ud558\uac70\ub098 \uc2a4\ud06c\ub9b0\uc0f7\uc744 \ucc0d\uc9c0 \uc54a\uc744 \uac83\uc774\ubbc0\ub85c \uc0dd\ub7b5\ud558\uace0, \uae30\ubcf8 \ub77c\uc774\ud2b8 \ud14c\ub9c8\ub85c \uc791\uc5c5\ud560 \uc218 \uc788\ub2e4. \uc790\uc720\ub86d\uac8c RallyTopAppBar\ub97c RallyTheme\ub85c \uac10\uc2f8\uc11c \uc218\uc815\ud558\uc790.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud0ed\uc774 \uc120\ud0dd\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud558\uae30<\/h2>\n\n\n\n<p>UI \uc694\uc18c \ucc3e\uae30, \uc18d\uc131 \ud655\uc778 \ubc0f \uc791\uc5c5 \uc218\ud589\uc740 \ub2e4\uc74c \ud328\ud134\uc5d0 \ub530\ub77c \ud14c\uc2a4\ud2b8 \uaddc\uce59\uc744 \ud1b5\ud574 \uc218\ud589\ub41c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>composeTestRule{.finder}{.assertion}{.action}<\/code><\/pre>\n\n\n\n<p>\uc774 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub294 &#8220;Accounts&#8221; \ub77c\ub294 \ub2e8\uc5b4\ub97c \ucc3e\uc544, \uc120\ud0dd\ud55c \ud0ed\uc758 \ub808\uc774\ube14\uc774 \ud45c\uc2dc\ub418\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-testing\/img\/baca545ddc8c3fa9.png?hl=ko\" alt=\"baca545ddc8c3fa9.png\" width=\"450\" height=\"800\"\/><\/figure><\/div>\n\n\n\n<p>\uc0ac\uc6a9 \uac00\ub2a5\ud55c \ub3c4\uad6c\ub97c \uc774\ud574\ud558\ub294 \uc88b\uc740 \ubc29\ubc95\uc740 <a href=\"https:\/\/developer.android.com\/jetpack\/compose\/testing-cheatsheet?hl=ko\">Compose Testing Cheat Sheet<\/a> \ub610\ub294 <a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/test\/package-summary?hl=ko\">\ud14c\uc2a4\ud2b8 \ud328\ud0a4\uc9c0 \ucc38\uc870 \ubb38\uc11c<\/a>\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc774\ub2e4. \uc6b0\ub9ac \uc0c1\ud669\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 finder\uc640 assertion\uc744 \ucc3e\uc544\ubcf4\uc790. \uc608) onNodeWithText, onNodeWithContentDescription, isSelected, hasContentDescription, assertIsSelected \ub4f1<\/p>\n\n\n\n<p>\uac01 \ud0ed\uc5d0\ub294 \ub2e4\ub978 \ucf58\ud150\uce20 \uc124\uba85\uc774 \uc788\ub2e4.<\/p>\n\n\n\n<ul><li>Overview<\/li><li>Accounts<\/li><li>Bills<\/li><\/ul>\n\n\n\n<p>\uc774\ub97c \uc54c\uace0, \ucf58\ud150\uce20 \ub0b4\uc6a9(content description)\uc744 \ucc3e\ub294 \ucf54\ub4dc\ub85c Thread.sleep(5000)\uc744 \uad50\uccb4\ud558\uace0, \ud574\ub2f9 \ucee8\ud150\uce20\uac00 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\uc790(assert).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Test\nfun rallyTopAppBarTest_currentTabSelected() {\n\u00a0 \u00a0 val allScreens = RallyScreen.values().toList()\n\u00a0 \u00a0 composeTestRule.setContent {\n\u00a0 \u00a0 \u00a0 \u00a0 RallyTopAppBar(\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 allScreens = allScreens,\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 onTabSelected = { },\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 currentScreen = RallyScreen.Accounts\n\u00a0 \u00a0 \u00a0 \u00a0 )\n\u00a0 \u00a0 }\n\n<strong>\u00a0 \u00a0 composeTestRule\n\u00a0 \u00a0 \u00a0 \u00a0 .onNodeWithContentDescription(RallyScreen.Accounts.name)\n\u00a0 \u00a0 \u00a0 \u00a0 .assertIsSelected()<\/strong>\n}<\/code><\/pre>\n\n\n\n<p>\uc774\uc81c \ud14c\uc2a4\ud2b8\ub97c \ub2e4\uc2dc \uc2e4\ud589\ud558\uba74 \ub179\uc0c9 \ud14c\uc2a4\ud2b8\uac00 \ud45c\uc2dc\ub41c\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-testing\/img\/251e68d36f6d08d9.png?hl=ko\" alt=\"251e68d36f6d08d9.png\"\/><\/figure>\n\n\n\n<p>\ucd95\ud558! \uccab \ubc88\uc9f8 Compose \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud588\ub2e4. \uac1c\ubcc4\uc801\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud558\ub294 \ubc29\ubc95\uacfc finder \ubc0f assertion\uc744 \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6e0\ub2e4.<\/p>\n\n\n\n<p>\uc774 \ud14c\uc2a4\ud2b8\ub294 \uc0c1\ub2f9\ud788 \uac04\ub2e8\ud588\uc9c0\ub9cc \ucef4\ud3ec\ub10c\ud2b8(\ucee8\ud150\uce20 \uc124\uba85 \ubc0f \uc120\ud0dd\ud55c \uc18d\uc131)\uc5d0 \ub300\ud55c \uc0ac\uc804 \uc9c0\uc2dd\uc774 \ud544\uc694\ud588\ub2e4. \ub2e4\uc74c \ub2e8\uacc4\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc18d\uc131\uc744 \uac80\uc0ac\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b0\uc790.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TopAppBarTest \ud30c\uc77c \uc0dd\uc131\ud558\uae30 AnimatingCircleTests.kt(app\/src\/androidTest\/com\/example\/compose\/rally)\uc640 \ub3d9\uc77c\ud55c \ud3f4\ub354\uc5d0 \uc0c8 \ud30c\uc77c\uc744 \ub9cc\ub4e4\uace0 TopAppBarTest.kt\ub77c\uace0 \uc774\ub984\uc744 \uc9d3\ub294\ub2e4. \ucef4\ud3ec\uc988\ub294 createComposeRule()\uc744 \ud638\ucd9c\ud558\uc5ec \uc5bb\uc744 \uc218 \uc788\ub294 ComposeTestRule\uacfc \ud568\uaed8 \uc81c\uacf5\ub41c\ub2e4. \uc774 \uaddc\uce59\uc744 \uc0ac\uc6a9\ud558\uba74 \ud14c\uc2a4\ud2b8 \uc911\uc778 Compose \ucf58\ud150\uce20\ub97c \uc124\uc815\ud558\uace0, \uc0c1\ud638 \uc791\uc6a9\ud560 \uc218 \uc788\ub2e4. ComposeTestRule\uc744 \ucd94\uac00\ud558\uae30 \uaca9\ub9ac\ub41c \ud14c\uc2a4\ud2b8 \ucef4\ud3ec\uc988 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub294 \uc608\ub97c \ub4e4\uc5b4 Espresso\ub97c \uc0ac\uc6a9\ud558\uc5ec Android View \uc5d0\uc11c \uc218\ud589\ud558\ub294 \uac83\uacfc \uc720\uc0ac\ud558\uac8c \uc571\uc758 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[38],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45758"}],"collection":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=45758"}],"version-history":[{"count":1,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45758\/revisions"}],"predecessor-version":[{"id":45759,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45758\/revisions\/45759"}],"wp:attachment":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=45758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=45758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=45758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}