안드로이드에서 테스트하기 - TDD 입문

이현우·2021년 8월 2일
3

Deep Dive: Android

목록 보기
7/10
post-thumbnail

이번 게시글에서는 본격적인 안드로이드에서의 테스트를 다루기 이전에, 테스트란 무엇이고 왜 하는 지, 안드로이드에서 테스트는 어떤 것들이 있는 지를 살펴볼 것이다. 또한 이러한 테스트를 잘 하기 위해서는 어떠한 방법으로 테스트를 설계하는 것이 좋을 것인지에 대한 일반적인 방법론도 살짝 살펴볼 것이다.
본 내용은 Advanced Android with Kotlin - Testing Basics의 내용 중 일부를 해석한 것이다.

Introduction to Android Testing

Testing

프로덕트를 개발하는 과정에 있어서 테스트는 굉장히 중요하다. 나의 앱이 잘 돌아"갈 것이다"와 나의 앱이 잘 돌아"간다"라는 차이에서 오는 감각이 이를 증명해준다. 테스트는 버그나 크래쉬에 대해서 큰 실마리가 되어줄뿐만 아니라 리팩토링을 할 때 테스트가 가능한 코드, 즉 이미 최적화가 되어진 코드를 제공해주어 개발 속도에 큰 차질을 빚지 않게 해준다. 또한 테스트는 코드 그 자체를 설명해주는 잘 정리된 문서 역할을 한다.

One of the many benefits of testing is that your tests act as a kind of documentation of what your code does.

Testing in Android

안드로이드에서 테스트는 크게 두 개로 구분지을 수 있다.

Local Test

JVM, 즉 코틀린 코드로 충분히 수행할 수 있는 테스트를 의미하며, 비즈니스 로직(혹은 그냥 로직)이 정확히 도는 지에 대한 검증을 수행할 수 있다.

Android Test

에뮬레이터나 실기기에서 수행할 수 있는 테스트의 일종이며 이 종류의 테스트를 수행할 시 에뮬레이터에서 테스트를 수행하는 것을 볼 수 있다. 따라서 로컬 테스트보다 보기 쉽고 로컬 테스트에서 수행하지 못하는 점들을 캐치하여 검증을 할 수 있지만 실기기를 이용하는 만큼 로컬테스트보다 테스트 속도가 느린 것이 단점이다.

Test Driven Development and Testing Strategies

TDD(Test Driven Development)

구현 목표를 테스트 코드를 통해 미리 설계를 해놓고 테스트의 결과가 참이 되게 구현을 해 나가는 방식을 의미한다. TDD의 결과를 결과가 검증된 프로덕트가 나오니 높은 퀄리티의 프로덕트가 나옴을 보장한다. 여기서 높은 퀄리티의 프로덕트란?

  • 에러나 버그가 절대 없다
  • 추가적인 요구사항이 있을 때 쉽게 요구사항을 반영할 수 있다, 즉 유지보수가 용이하다

Testing Strategies For Readable Tests

위에서 말했듯 테스트는 그 코드를 설명하는 하나의 문서이기도 하니, 테스트 코드를 작성한다면 잘 작성해야할 필요가 있다. 이를 용이하게 하기 위한 방법들은 다음과 같다.

  • 테스트의 이름을 잘 지어라

    • 다음과 같이 구조화하는 것을 추천한다

    테스트의 목적_로직이나 입력값_결과상태

    ​ ex) getActiveAndCompletedStats_noCompleted_returnsZeroHundred

  • 3개의 단계로 구분지어 테스트를 구조화 시켜라 Given/When/Then

    • Given
      • 테스트 전에 필요한 객체나 데이터 준비
    • When
      • 객체, 데이터에 테스트를 할 함수를 사용하여 객체, 데이터에 상태 변화를 유도
    • Then
      • 변화된 값이 예상된 값과 맞는 지 체크를 한다
  • Assertion Framework를 잘 사용해라

// JUnit
assertEquals(result.completedTasksPercent, 0f)

// Assertion Framework(hamcrest, truth)
assertThat(result.completedTasksPercent, `is`(0f))

결국 테스트 코드는 우리가 읽기 쉽게 적어야 하기에 이런 유틸들을 가져와서 사용하는 것을 권장한다.

Test Scope

앱을 테스트를 할 때 어느정도로 테스트를 할 것인지도 중요한데, 그 범위는 세가지로 정리할 수 있다.

  • Unit Test
  • Integration Test
  • End to End Test

Unit Test (70%)

  • 함수, 클래스에 행해지는 테스트
  • 기능 동작에 대한 검증을 한다
  • 주로 Local Test로 수행

Integration Test (20%)

  • 여러가지의 클래스로 이뤄진 하나의 기능을 테스트할 때

  • 여러가지의 클래스가 맞물려지는 형태에 대한 검증

  • 상황에 따라서 Instrument 테스트, 로컬 테스트 모두 돌아갈 수 있음

End to End Test (10%)

  • 느려, 모든 기능에 대해서 테스트를 함
  • 따라서 Instrument 테스트로 하는 것이 일반적임

왜 기능을 분리해야하는가? 테스트의 관점에서

만약에 Activity에 모든 코드를 다 때려박았다면? 액티비티를 테스트 할 때, End-to-End의 의미에서의 테스트만 가능하지 Unit, Integration Test는 사실상 불가능하다. 그래서 기능을 아키텍처로 쪼개는 것이다.

Unit Test를 시행하기 좋은 곳

  • ViewModel
  • Repository
  • Dao

Integration Test

  • Fragment+ViewModels
  • Database

그렇다면 내 앱이 테스트가 불가능한 이 큰 문제인가요?

A) 아 그건 아님, TDD에서 궁극적인 목적은 결국 버그가 없는 프로덕트이기에 테스트가 없는 리팩토링 보다는 테스트 코드를 하나라도 작성하는 것이 유의미한 검증을 하는 것이다

profile
이현우의 개발 브이로그

0개의 댓글