-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Share] 안드로이드 Unit Test를 통해 느낀 테스트의 여러가지 #2
Comments
이슈 템플릿(Topic/Detail 분리)정도만 지켜주세요!! |
글 잘 읽었습니다! 개발 알못, 안드 알못이 궁금해서 질문 드립니다.
|
|
이제 확인했습니다! ㅠ.ㅠ |
|
둘 다 해당됩니다. MVVM이나 MVP과 같은 디자인 패턴에서 Viewmodel, Presenter를 사용하는 이유는 UI(View)와 비즈니스 로직(Model)을 완전하게 분리하기 위함입니다. 조금 더 들어가면 여러 차이점이 있긴 하지만 결국 컨트롤러(Viewmodel, Presenter) 단에서 UI로직을 추상화하면 테스트하기도 쉬워진다는 이점이 있습니다. 다만 이 글은 테스트 관점에서 쓴 글이어서 테스트를 조금 더 부각시켰습니다. |
@boohyunsik 넵넵 조금 더 질문을 구체화하면, mokito와 같은 테스트 도구들을 사용하면 굳이 추상화를 하지 않아도 mocking을 할 있는데 테스트를 위해서 추상화를 시킨다라고 느꼈어서 위의 질문을 단 것이었습니다! |
개인적으로는
|
아 pojo! 그동안 포조의 개념이 아리송했는데 이제 이해가 가네요. 감사합니다! |
@sojeongw |
@AgwaB 지금까지의 생각을 말씀드리자면,
이런식으로 추상화 -> 테스트편리화 로 이야기를 합니다. 물론 질문이었던 '추상화를 해야 mocking을 할 수 있는가?'에 대해서는 아닌것같지만, |
일반 객체도 라이브러리를 이용하면 쉽게 mocking 할 수 있지만, 제가 지향하는점은 라이브러리의 도움이 없어도 테스트하기 편한 코드를 짜는게 더 좋을것 같다는 점입니다. 이 점은 객체 지향 프로그래밍에서 강조하는 개방-폐쇄 원칙, 또는 전략 패턴과도 어느정도 일맥상통한다고 생각합니다. |
|
@inDlife @boohyunsik 넵넵 맞습니다. 저도 저런 제 코드를 테스트 하면서 자괴감이 들곤 했습니다ㅠㅠㅠ 그래서 의도한 건 최대한 테스트 하려는 method의 의도가 들어나고, 의도를 헤치지 않으려는 선에서만 mocking을 한 기억이 있네요. |
프러덕션 코드에 남아있는 걸 말합니다. 이런 과정을 보고 모킹을 하나의 추상화로 볼 수 있나보다 라고 생각했어요. 토비스프링이 한 주제를 가지고 단계적으로 설명하다보니 그 부분이 어디인지 콕 찍어말하기가 애매하네요 ㅜㅜ 5장을 다시 볼 때 그부분을 보면 얘기드릴게요. |
|
안드로이드 Unit Test 작성 방법
안드로이드는 Gradle을 이용하여 빌드되기 때문에, Gradle 표준으로 작성할 수 있습니다.
보통
src/test
디렉토리에 테스트 파일을 만들며, 패키지는 src와 똑같이 구성하며 클래스 이름 뒤에 Test를 붙이는 것이 특징입니다.Test는 Java Unit Test framwork인
JUnit
을 이용하며, 따라서 assert와 같은 Java Unit Test 문법을 그대로 활용할 수 있습니다. 이에 더해Mockito
,PowerMock
,Robolectric
과 같은 다양한 Java Testing Library를 활용할 수도 있습니다.안드로이드 Unit Test 작성 시 어려움
안드로이드는 Device dependency가 상당히 강한 프레임워크입니다.
모든 앱은 안드로이드 OS가 설치된 디바이스 위에서 동작하고, 안드로이드 컴포넌트들은 컴퓨터의 JVM위에서 만들 수 없습니다. 따라서 컴퓨터의 JVM이 실행하는 안드로이드 유닛 테스트에서 안드로이드 컴포넌트 객체를 만들거나 사용하려 할 때, 많은 문제가 발생합니다. (Null-pointer exception 등..)
Mocking
이런 문제를 해결하기 위해 보통
Mock
이라는 개념을 사용합니다. 흔히 객체를Mocking
한다라 하면, 테스팅을 위해 가짜 객체를 만드는 것 정도로 이해할 수 있습니다. Java의Mockito
,PowerMock
과 같은 테스팅 라이브러리들은 이런 Mocking을 편리하게 지원합니다.위의 코드에서 Context는 안드로이드 OS에서 생성하는 앱의 정보를 담고있는 객체입니다.
@Mock
이라는 어노테이션을 이용하여 선언해주면 편리하게 Mock Context 객체를 생성할 수 있습니다.Mock 객체를 이용하면 위의 코드와 같이 특정 함수 콜에 대한 응답을 내가 원하는 응답으로 설정할 수 있습니다. Context 객체는 내 컴퓨터의 JVM 위에서는 정상적으로 만들어지지 않으니, 이렇게 Mock 객체를 이용하여 필요한 함수 call에 대한 응답을 바꿔가며 테스트를 진행합니다.
DI 활용
안드로이드에서는 Intent, Bundle과 같이 필요할 때 객체를 생성하여 사용하는 경우가 있습니다. 또는 서버에 요청을 하기 위해 다양한 라이브러리를 활용하기도 합니다. 그러나 이런 클래스들도 framework 의존성이 강하기 때문에, 테스트시 문제를 야기하는 경우가 많습니다. 이런 경우는 Mock 객체를 주입해주기 위해
의존성 주입
을 활용합니다.위의 메소드를 테스트 하려면, 내 컴퓨터의 JVM은 Intent를 정상적으로 만들어낼수 없기 때문에 NPE를 유발합니다. 따라서 위와 같은 경우는 Intent를 주입받는 식으로 작성하는게 좋습니다.
그리고 아래와 같이 테스트 할 수 있습니다.
그러나...
그러나 여러 Unit Test를 작성하면서, 모든 프레임워크 의존적인 컴포넌트들에 Mock 객체를 만들고, 원하는 응답을 설정해주는 것이 만만하지 않다는 것을 느꼈습니다. 많은 고민 끝에, Mock 객체를 최소화 하도록 코드를 설계하는 것이 더 좋은 해결방안이라는 생각이 들었고, 그 방법들을 어떻게 활용할 수 있는지 간단하게 설명해보겠습니다.
MVP, MVVM 패턴
안드로이드 앱을 작성하다보면(안드로이드 이외에 다른 앱 개발에도 많이 사용되지만)
MVP 패턴
,MVVM 패턴
에 관한 이야기들을 많이 들을 수 있습니다. 이런 패턴을 사용하는데는 다양한 이유가 있지만, 그 중 테스트 가용성에 대해 이야기해보려 합니다. 안드로이드에서 가장 프레임워크 의존성이 강한 컴포넌트가 바로 Activity, Fragment와 같은 UI 컴포넌트 입니다. 이 클래스들은 안드로이드 OS에서 LifeCycle등을 관리하고, 객체를 만들어주기 때문에 컴퓨터의 JVM에서 UI 컴포넌트 객체를 만들어 테스트 할 수 없습니다. 따라서 UI와 연관된 Acitivty, Fragment를 상속받는 클래스에서는 최대한 UI 동작과 관련된 로직을 작성하고, 그 이외의 모든 비즈니스 로직은Presenter
또는View Model
에서 작성합니다. 이렇게하면 모든 비즈니스 로직을 Activity에 작성할때 매우 까다로웠던 테스트를, 프레임워크와 의존성이 적은Presenter
나View model
을 테스트로 대체할 수 있습니다. 또한 Mocking을 위해 View interface를 작성해 UI 컴포넌트를 추상화해주는 작업또한 테스트 가용성을 위해 필수적으로 요구됩니다.Clean Architecture
Clean Architecture는 엉클-밥 으로 유명한 Robert. C Martin이 제안한 소프트웨어 디자인 원칙으로, 핵심은 프레임워크와 완벽하게 독립된, 순수 Java코드로 구현된 layer를 갖는 구조입니다.

클린 아키텍쳐에서는
UseCase
라는 비즈니스 로직을 구현한 계층을 구현하는데, 이 계층은 순수 자바코드로 이루어져 있고, Framework 의존적인, 예를 들면 안드로이드 dependency가 강한 객체, 서버에 요청을 보내는 객체등이 존재하지 않습니다. 그리고 이 UseCase들의 조합으로 프로그램을 작성하게 됩니다. 이렇게 코드를 작성하면, 프레임워크 의존성이 떨어지게 되어 테스트하기 매우 간편해진다는 장점이 있습니다.The text was updated successfully, but these errors were encountered: