{"id":26833823,"url":"https://github.com/mr-won/android_unittest","last_synced_at":"2026-01-11T16:03:41.018Z","repository":{"id":240553958,"uuid":"802948094","full_name":"mr-won/Android_UnitTest","owner":"mr-won","description":"[Android] 테스트 코드 작성해보기","archived":false,"fork":false,"pushed_at":"2024-05-19T17:35:57.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T02:27:02.708Z","etag":null,"topics":["junit","test-code","uitest"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mr-won.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-19T17:27:43.000Z","updated_at":"2024-05-19T17:36:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"0d117e38-bc66-48ff-9bfe-0034e0b9956e","html_url":"https://github.com/mr-won/Android_UnitTest","commit_stats":null,"previous_names":["chihyeonwon/android_unittest","chihyunwon/android_unittest","mr-won/android_unittest"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mr-won%2FAndroid_UnitTest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mr-won%2FAndroid_UnitTest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mr-won%2FAndroid_UnitTest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mr-won%2FAndroid_UnitTest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mr-won","download_url":"https://codeload.github.com/mr-won/Android_UnitTest/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246338449,"owners_count":20761378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["junit","test-code","uitest"],"created_at":"2025-03-30T15:30:05.823Z","updated_at":"2026-01-11T16:03:41.001Z","avatar_url":"https://github.com/mr-won.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Android_UnitTest\n[Android] 테스트 코드 작성해보기\n[안드로이드 Test 공식 개발 문서](https://developer.android.com/training/testing/local-tests?hl=ko)\n## 테스트 코드를 작성하는 이유\n당연한 답변이 될 수도 있겠지만, 구현한 동작이 올바르게 동작하는지 검증하기 위해 테스트 코드를 작성하는 것이다.    \n특히, 어떤 코드를 단순히 리팩토링할 때 기존과 다르게 동작할 수 있는 노릇이다.     \n따라서 이런 상황을 대비하여 일일히 수동으로 테스트를 해보기 보단, \n다양한 엣지 케이스들을 고려한 테스트 케이스를 코드로써 작성해두면 편리하게 동작의 무결성을 보장할 수 있을 것이다.     \n\n## Andriod 에서의 테스트\n안드로이드는 사용자와 인터랙션하는 UI 까지 구현하기 때문에, 단순히 화면에 보여지지 않는 테스트 뿐만 아니라     \nUI 인터랙션이 정상적으로 이루어지는지 검증하기 위한 UI 테스트까지 고려하게 된다.     \n따라서 아래와 같이 두 가지 종류의 테스트가 존재한다.     \n\n## Unit Test\n\n'테스트 코드'라고 했을 때 가장 일반적으로 떠올리게 되는 테스트이다. \n말 그대로 코드를 유닛 단위로 기능을 검증하는 것이다.     \n유닛 단위라 함은 메소드, 클래스 등이 될 수 있다.    \n\n안드로이드에서는 JUnit, Mockito, PowerMock 등을 사용할 수 있다.    \n\n## UI Test\n\n위에서 말한 것처럼 안드로이드에서는 UI 테스트를 고려하게 된다. \n사용자와의 인터랙션을 검증하게 된다. \n사용자 인터랙션이라 함은 버튼 클릭, 테스트 입력, 스크롤 등이 될 수 있다.\n\nEspresso, UIAutomator, Robotium, Calabash, Robolectric 등의 툴을 사용하여 테스트 코드를 작성해볼 수 있다.\n\n## Android 프로젝트에서의 테스트\n안드로이드 스튜디오에서 프로젝트를 생성하면 테스트 관련 툴이 자동으로 추가된다.     \napp 단위의 build.gradle 파일의 의존성 쪽을 보면 아래와 같은 구문들이 추가되어 있는 것을 볼 수 있다.   \n```kotlin\ntestImplementation 'junit:junit:4.+'\nandroidTestImplementation 'androidx.test.ext:junit:1.1.2'\nandroidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'\n```\nJUnit, Espresso 등 Unit 테스트 툴과 UI 테스트 툴이 기본적으로 탑재된다.      \n      \n그리고 프로젝트 디렉토리만 보더라도 테스트 관련 파일을 확인해볼 수 있다.    \n     \nandroidTest, test 등 디렉토리 안에 테스트 파일들이 있다.      \nandroidTest 디렉토리 안에는 UI 테스트 관련 파일들이 있고, test 디렉토리 안에는 Unit 테스트 관련 파일들이 있다.        \n\nJUnit 을 통한 Unit 테스트를 사용해본다.      \n\n## JUnit 사용방법\nExampleUnitTest 파일을 보면 아래와 같은 모습이다.\n```kotlin\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 2)\n    }\n}\n```\n\n@Test 라는 어노테이션과 함께 덧셈 연산을 테스트하는 메소드가 있다. \n이 메소드 안에서는 assertEquals() 라는 메소드를 통해 4와 2 + 2 를 비교하는듯한 모습을 보이고 있는데,\nassertEquals() 의 모양을 살펴보자.\n```kotlin\n/**\n * Asserts that two longs are equal. If they are not, an\n * {@link AssertionError} is thrown.\n *\n * @param expected expected long value.\n * @param actual actual long value\n */\npublic static void assertEquals(long expected, long actual) {\n    assertEquals(null, expected, actual);\n}\n```\nexpected 와 actual 파라미터 두 개를 비교하여 같은 값을 갖고 있는 지에 대해 검사하는 동작을 한다.\n```\nAssert 는 '단언하다, 주장하다' 라는 뜻을 갖고 있다.\n실생활에서 '주장'이라 함은 올바르고 틀린 것을 따지기보단 단지 자신의 의견을 표출하는 것 뿐이다.\n마찬가지로 테스트 코드에 있어 Assert 도 일단 실행을 해보고, 이것이 올바르게 동작했다면 통과하고\n만약 올바르게 동작하지 않았다면 AssertionError 를 쓰로잉하게 된다.\n```\n\n아까 살펴봤던 기본 예제 코드에서 '4' 와 '2 + 2' 를 비교했는데, 이 두 값은 같으므로 Unit 테스트를 통과하게 되는 것이다.     \n\n그럼 이 테스트는 어떻게 실행하는 것일까?       \n\n테스트 코드는 이렇게 실행할 수 있다. 테스트 파일을 우클릭해보면 다음과 같은 메뉴가 있는데,       \n이를 실행하면 된다. (혹은 적혀있는 단축키를 눌러도 된다)    \n\n![image](https://github.com/chihyeonwon/Android_UnitTest/assets/58906858/646f3f5f-e0e1-4e99-a58e-78bbc60e977d)\n\n그렇게 되면 아래와 같이 테스트 성공이라는 표시가 뜬다.     \n  \n![image](https://github.com/chihyeonwon/Android_UnitTest/assets/58906858/fde68737-fc69-4768-b864-b79022d7f19f)\n\n만약 테스트 코드를 다음과 같이 작성했다고 해보자.       \n이는 기능이 제대로 동작되지 않는 상황을 가정한 것이다. 4 라는 값을 기대하는 유닛 테스트인데, 연산 결과가 5인 상황이다.      \n```kotlin\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 3)\n    }\n}\n```\n![image](https://github.com/chihyeonwon/Android_UnitTest/assets/58906858/d5fd38ac-7fe4-44ef-8c5e-7290655afce5)\n\n'Tests Failed' 라고 뜨며 어떤 테스트 케이스가 통과되지 못했는지 (실패했는지) 에 대한 정보를 제공해준다.       \n이런 식으로 테스트가 실패한 동작에 대해 디버깅을 수행하면 된다.    \n\n유닛 테스트 코드를 작성하면 (귀찮지만) 다양한 테스트 케이스들을 고려해볼 수 있기 떄문에 기능 추가, 변경, 혹은 코드 리팩토링에 있어 강력한 이점을 지닌다.      \n다른 기능에 비해 특히나 동작의 무결성이 보장되어야 하는 부분이라면, 테스트 코드의 중요성은 더욱 높아진다.     \n\n## 직접 Unit 테스트 코드 작성해보기\n\n\n실제 사례(?)를 바탕으로 연습해봤다.\n간단하게 계산기 클래스를 만들어 덧셈, 뺄셈이 정상적으로 이루어지는지에 대해 검증해보았다.\n\n클래스를 아래와 같이 만들어준다.\n```kotlin\nclass Calculator {\n\n    fun add(a: Int, b: Int): Int {\n        return a + b\n    }\n    \n    fun sub(a: Int, b: Int): Int {\n        return a - b\n    }\n\n}\n```\n\n그리고 아까 ExampleUnitTest 파일이 있던 경로에 계산기 기능 검증 테스트를 위한 CalculatorTest 라는 테스트 파일을 만들어준다.     \n그리고 아래와 같이 코드를 작성해볼 수 있다.     \n\n```kotlin\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\n\nclass CalculatorTest {\n    private var calculator: Calculator? = null\n\n    @Before\n    fun setUp() {\n        calculator = Calculator()\n    }\n\n    @Test\n    fun 기본_덧셈() {\n        val result = calculator?.add(5, 6)\n        assertEquals(11, result)\n    }\n\n    @Test\n    fun 기본_뺄셈() {\n        val result = calculator?.sub(10, 5)\n        assertEquals(5, result)\n    }\n\n}\n```\n몇 가지 어노테이션에 대해 설명하자면 다음과 같다.\n- @Before    \n테스트 시작전 실행되어야 할 동작 (객체 초기화 등)     \n- @Test   \n@Before 이후 돌아가는 테스트 케이스 코드     \n그리고 위 코드에선 그닥 의미가 없지만 이런식으로 엣지 케이스들도 고려해줄 수 있겠다.\n```kotlin\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\nimport org.junit.Before\n\nclass CalculatorTest {\n    private var calculator: Calculator? = null\n\n    @Before\n    fun setUp() {\n        calculator = Calculator()\n    }\n\n    @Test\n    fun 기본_덧셈() {\n        val result = calculator?.add(5, 6)\n        assertEquals(11, result)\n    }\n\n    @Test\n    fun 음수끼리_덧셈() {\n        val result = calculator?.add(-5, -4)\n        assertEquals(-9, result)\n    }\n\n    @Test\n    fun 기본_뺄셈() {\n        val result = calculator?.sub(10, 5)\n        assertEquals(5, result)\n    }\n\n    @Test\n    fun 음수끼리_뺄셈() {\n        val result = calculator?.sub(-5, -4)\n        assertEquals(-1, result)\n    }\n\n}\n```\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmr-won%2Fandroid_unittest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmr-won%2Fandroid_unittest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmr-won%2Fandroid_unittest/lists"}