Unit Test 시작하기

안녕하세요. Android 플랫폼에서 화해 앱을 개발을 하고 있는 남궁혜인입니다. Unit Test

 

오늘 포스팅에서는 때때로 개발자들의 발목을 잡기도 하지만 사전에 문제를 예방할 수 있도록 하여 개발하는 데 큰 도움을 주기도 하는 테스트에 대한 얘기를 나누어 보려 합니다.

 

 

그럼 테스트란 무엇인지부터 한번 알아볼까요 ?

 

 


 

단위 테스트(Unit Test)란 무엇인가?

위키피디아에 정의된 내용 일부를 발췌해 보면 아래와 같습니다.

 

💡 유닛 테스트는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스를 작성하는 절차를 말한다.
출처 위키피디아 유닛 테스트란?

 

이처럼 단위 테스트는 우리가 작성한 코드가 의도한 대로 작동하는지 검증하기 위한 절차로 문제를 방지하는 기능도 있지만, 부수적으로 코드 변경에 의한 사이드 이펙트를 최대한 줄일 수 있는 예방책이 되기도 합니다. 또한, 서비스 요구사항 변경이나 리팩토링으로 인해 코드 수정이 필요한 상황에서 더 유연하고 안정적인 대응을 할 수 있게 되고, 테스트 코드를 작성하는 과정에서 자연스럽게 코드의 모듈화를 고민하게 되는 등의 부수적인 이점들도 가지고 있다고 생각합니다.

 

 

 

 

테스트의 종류

테스트는 테스트 대상 범위나 성격에 따라 UI Test, Integration Test(통합 테스트), Unit Test(단위 테스트) 등 3가지로 구분합니다. 아래 그림을 한번 볼까요?

 

 

 

Unit Test_테스트 기본 요소

출처 테스트 기본 요소 – 안드로이드 개발자 공식문서

 

 

테스트에 관심이 있으셨던 분이라면 한 번쯤은 보셨을 테스트 피라미드입니다. 한 단계씩 살펴보며 각 구성에 대해 알아보도록 하겠습니다.

 

 

 

Unit Test (단위 테스트)

소형 테스트에 속하는 단위 테스트는 클래스 범주 내에서 작은 단위(함수 단위)의 기능에 대한 유효성을 검증하는 테스트입니다. 단위 테스트는 매우 간단하고 명확하며 빠르게 실행된다는 특징이 있습니다. 쉽게 말하면, 하나의 함수에 대해 하나 이상의 테스트가 존재할 수 있고, 각각의 조건에 대한 유효성을 검증합니다. 이렇게 작성된 단위 테스트가 많을수록 해당 로직에 대한 신뢰도가 높아질 수 있습니다. 또한, 작게 쪼개진 단위 테스트는 해당 로직이 어떤 역할을 하는지 쉽게 파악할 수 있다는 장점이 있습니다.

 

Android의 단위 테스트는 실행되는 위치에 따라 로컬 단위 테스트와 계측 단위 테스트 2가지로 구분합니다.

 

로컬 단위 테스트

Android Framework와는 별개로 동작하는 테스트를 말하며, 로컬 JVM에서 실행되는 테스트입니다. 로컬 단위 테스트는 빠르게 실행된다는 장점이 있습니다.

계측 단위 테스트

실제 기기 또는 에뮬레이터에서 실행되는 테스트로 로컬 단위 테스트보다 실행 시간이 오래 걸립니다. 따라서, 실제 기기에서 하드웨어에 관한 앱의 동작을 테스트해야 하는 경우에만 이 방법을 사용하는 것이 좋습니다.

 

 

 

Integration Test (통합 테스트)

중형 테스트에 속하는 통합 테스트는 서로 다른 모듈 혹은 클래스 간 상호작용의 유효성을 검사하는 테스트입니다. 이러한 통합 테스트가 필요한 이유는 각각의 단위 테스트가 검증되었다 하더라도, 모듈 간 인터페이스 및 데이터의 흐름이 의도한 대로 제대로 동작하지 않는 경우도 있기 때문에 조금 더 넓은 범위에서 추가적인 테스트가 필요합니다.

 

 

Unit Test_통합테스트의 필요성

위와 같은 상황을 방지하기 위해 통합테스트가 필요합니다.

출처 stackoverflow

 

 

또한 통합 테스트는 각 모듈에 대한 설정 또는 테스트를 하기 위해 사전 조건이 필요한 경우도 있기 때문에 단위 테스트에 보다 테스트 코드를 작성하기가 복잡합니다. 하지만 단위 테스트보다 더 넓은 범위의 종속성까지 테스트함으로써 단위 테스트보다 좀 더 유의미한 테스트가 되는 경우가 많습니다.

 

 

 

UI Test

대형 테스트로 분류되는 UI 테스트는 실제 사용자들이 사용하는 화면에 대한 테스트를 하여 서비스의 기능이 정상적으로 작동하는지 검증하는 테스트입니다.

 

UI 테스트는 실제 앱을 사용하는 사용자의 흐름에 대해 테스트 함으로써 UI 변경 사항으로 인해 발생할 수 있는 문제를 사전에 차단하여 앱의 신뢰도를 높일 수 있습니다. 하지만 화면과 직접적으로 연관되어있는 테스트이다 보니 실행 시간도 오래 걸리고, 디자인이 변경될 때마다 테스트 코드의 수정이 필요하므로 유지 보수 비용도 큰 편입니다.

 

Android는 화면 크기도 다양하고, 버전에 따라 구성이 다를 수 있어서 실제 기기에서 테스트하는 것도 좋지만 Firebase Test Lab 또는 에뮬레이터를 활용하여 다양한 기기에 대한 테스트를 진행하는 것이 효율적일 것입니다.

 

이처럼 테스트 피라미드에서는 테스트하고자 하는 단위와 목적에 따라 테스트를 구분하고 있습니다. 단위 테스트는 가장 작은 단위인 함수를 검증하고, 통합 테스트는 모듈 간 상호작용이 올바르게 동작하는지 검증하고, UI 테스트는 가장 마지막으로 진행되는 테스트로 사용자 인터랙션이 오류 없이 동작하는지 검증합니다.

 

그런데 왜 피라미드 형태로 표현되었을까요? 각각의 테스트의 단위와 목적이 다른 만큼 테스트 코드를 작성하는 데에 필요한 비용도 다릅니다. 피라미드에서 가장 아래에 있는 단위테스트는 테스트 범위가 작기 때문에 작성이 수월하고, 하나의 테스트 당 검증하려는 범위가 작기 때문에 무수히 많은 테스트들이 작성될 수 있습니다. 그리고 통합 테스트는 이러한 단위 테스트를 결합하여 조금 더 넓은 범위에 대해서 검증하기 때문에 고려해야 할 부분이 더 많아서 단위 테스트보다는 더 많은 비용이 필요합니다. 마지막으로 UI 테스트는 위에서 설명한 것과 같은 이유로 가장 많은 비용과 시간이 필요하지만 사용자 시나리오를 기반으로 작성하다보니 테스트 코드의 양은 적습니다. 마지막으로 UI 테스트는 위에서 설명한 것과 같은 이유로 가장 많은 비용과 시간이 필요하지만 사용자 시나리오를 기반으로 작성하다보니 테스트 양은 적습니다.

 

이러한 이유로 구글 공식 문서에도 확인할 수 있듯이 각 테스트의 비율은 단위 테스트 70%, 통합 테스트 20%, UI 테스트 10%로 구성하는 것이 좋습니다.

 

테스트의 단계에 대해 하나씩 살펴보았습니다. 테스트를 처음 도입하는 분들이라면 비교적 작성에 비용이 적게 드는 단위 테스트부터 시작해보는 것을 추천합니다.

 

 

 

 

테스트 코드 작성은 왜 어려울까?

우리가 테스트의 중요성을 알고 있으면서도 쉽게 시작하지 못하는 이유는 무엇일까요?

 

 

테스트 코드를 작성할 시간이 부족해!

제가 테스트 코드를 작성하는 데 있어서 가장 어려웠던 부분은 항상 시간이 부족하다는 것이었습니다. 그렇다면 왜 시간이 부족 했을까요?

 

테스트 코드 작성을 고려하지 않은 채로 개발 일정을 산정해 두고 그 시간 내에서 테스트 코드를 같이 작성하려고 하다 보니 테스트 코드를 작성하지 못한 채로 프로젝트 기간이 끝나는 경우가 대부분이었습니다.

 

이러한 문제를 해결하기 위해서 작업 일정을 산정할 때 테스트 코드 작성을 위한 기간을 별도로 계획하려고 노력하고 있습니다. 이렇게 할 수 있었던 이유는 함께 일하는 팀원들이 테스트 코드의 필요성에 대해 공감하고 있었기에 추가 시간을 확보할 수 있었기 때문입니다. (팀원들이 공감하지 못한다면, 먼저 테스트 코드의 중요성에 대해서도 함께 논의해보면 좋을 것 같습니다.)

 

 

 

 

 

코드 변경이 필요할 때 유지 보수할 코드의 양이 늘어날 것 같아!

단순히 코드의 라인 수만 생각했을 때, 구현 내용이 변경된다면 테스트 코드도 개선되어야 하므로 관리해야 할 코드의 양이 늘어나는 것은 맞습니다. 하지만 관리 대상이 늘어난다는 단점보다 테스트 코드를 유지함으로써 얻는 이점이 더욱더 많습니다. 다양한 테스트 케이스가 작성되어 있다면 기능이 변경되거나 코드를 개선할 때 오히려 개발 시간을 단축할 수도 있습니다. 예를 들어 요구 사항 변경 요청이 들어왔을 때 테스트 코드를 통해 영향 범위를 빠르게 파악할 수 있고, 실패하는 테스트를 통해 일어날 수 있는 문제를 미리 발견할 수 있습니다. 이는 테스트 코드 작성으로 인해 얻을 수 있는 최대 이점이라고 생각합니다.

 

이러한 장점을 위해서는 테스트가 항상 실패 없이 실행되도록 유지해야 합니다. 그러면 유지보수에 소비하는 시간을 단축할 수 있을 것입니다. 저희 안드로이드 플랫폼에서는 CI(지속적인 통합)를 통해 주기적으로 테스트 코드 유효성을 확인하고 있습니다. 정기적인 빌드를 통해 테스트가 실패하는 케이스를 빠르게 찾아낸다면, 실패로 인한 테스트 수정 범위도 좁힐 수 있고 코드를 수정하기 위한 시간도 절약할 수 있습니다.

 

 

 

테스트는 어디서부터 시작해야 하는 걸까?

막상 테스트 코드를 작성하기 위한 시간이 확보되더라도 어디서부터 어떻게 해야 할지 막막하고 어렵게 느껴지는 경우가 있습니다.

 

그렇다면 먼저 단위 테스트 작성부터 시작해 보시길 바랍니다. 테스트 피라미드에서도 보았듯이 대형 테스트로 갈수록 작성 및 관리 비용이 크니 간단하고 빠르게 실행할 수 있는 단위 테스트부터 시작해보시는 것을 추천해 드립니다.

 

다만 이때 “하나의 테스트에서 하나의 기능만 검증한다”는 점을 꼭 기억하세요!

 

하나의 테스트에서 여러 기능을 검증하려고 하면 자연스럽게 테스트의 크기가 커지고 그 결과 테스트가 실패했을 때 정확한 원인을 파악하는 시간이 더 오래 걸리게 됩니다.

 

이후 테스트에 흥미가 느껴지신다면 FIRST, Right-BICEP, CORRECT 등 테스트 코드를 작성하는 데 참고하면 좋을 개념들에 대해서도 한번 찾아보시기 바랍니다. 더욱 의미 있는 테스트 코드를 작성하는 데 큰 도움이 될 것입니다.

 

 

 

 

마치며

이번 글은 테스트를 작성하기에 앞서, 테스트의 개념과 종류, 그리고 제가 테스트 작성하는 것이 어려웠던 이유와 그것들을 어떻게 해결하였는지에 대해 공유해보았습니다.

 

테스트 코드를 작성하기 위해서는 개발자뿐만 아니라 같이 일하는 다른 동료들 모두가 테스트 코드의 중요성에 대해 공감하고 필요성을 느껴야 비로소 테스트 코드를 효율적으로 활용할 수 있다고 생각합니다. 그래서 화해 안드로이드 플랫폼에서는 테스트 코드를 효율적으로 작성 및 관리하는 방법과 더불어 협업하는 동료들에게 테스트의 중요성을 인지시킬 수 있는 방법에 대해서도 꾸준히 논의를 이어 나가고 있습니다.

 

다음 글에서는 안드로이드 플랫폼에서 테스트 코드를 작성하는 방법에 대해 이야기를 해 보도록 하겠습니다.

긴 글 읽어주셔서 감사합니다!

 

 

Unit Test


 

 

 

 

채용정보 확인하기

 

 

14
by nc nd