-
Notifications
You must be signed in to change notification settings - Fork 2
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
[TEST] Today Unit test 작성 (#197) #201
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생했습니다~ mock stub spy에 대한 기준을 같이 정해서 분리해봅시다
|
||
@testable import LionHeart_iOS | ||
|
||
final class TodayViewModelSpy: TodayViewModel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 ViewController를 test할때 ViewModelStub를 만들어서 사용했는데
코드를 보니 Spy를만들어서 사용한걸보고 공부를해보니
우리가 단순히 output이 잘나오는지만 확인할거면 Stub가 맞는데
지금처럼 output에 대한 검증을 포함해 실제 어떤 내부 stream이 값이 잘들어가거나 어떤 메서드가 호출이되었다는 행위에대한 검증이 함께 필요해서 spy를 사용하신게 맞나용
제가 이해한 방식입니다
mock은 어떤 메서드가 잘호출되었는지 여부를 검증 -> 행위에대한 검증 객체
stub는 어떤 output이 잘 return되었는지 여부를 검증 -> 상태에대한 검증 객체
spy는 어떤 메서드가 잘 호출되었는지 + output이 잘return되었는지 여부를 검증 -> 상태와 행위에 대한 검증 객체
만약에 제가 이해한게 맞으면 제 ViewController를 test할때 ViewModel도 Spy라는 네이밍이 적절해보이네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 말씀해주신게 맞습니다! 저도 동일하게 이해했습니다 😊
@testable import LionHeart_iOS | ||
|
||
|
||
final class TodayNavigationSpy: XCTestCase, TodayNavigation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제가 위에 남긴 리뷰가 맞다면
해당 navigation구현객체는 단순히 어떤 메서드의 행위에 대한 검증을 진행하는 객체이므로 Spy보다는 Mock이라는 네이밍이 맞지 않을까요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다시 로직을 확인해보니 저희는 TodayNavigation을 정말 자리만 채워줄뿐인 용도로 사용하고 있어서 Spy
랑 Mock
이 아닌 Dummy
가 맞아보이네요! 수정하겠습니다!
|
||
func test_투데이_아티클_조회_API_올바른데이터_성공() throws { | ||
// Given | ||
let expectation = XCTestExpectation(description: "Today Article API 성공적으로 Output으로 전달") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XCTestExpectation를 저는 when에다가 두긴 헀는데
Before you perform an asynchronous task in your test method, create an instance of XCTestExpectation with a description of the task.
공식문서를 보니 비동기처리를 하기전에 XCTestExpectation객체를 생성하라는걸보니 given에 둬서 해당 함수가 비동기적으로 호출할 준비를 해준다는 느낌으로 가져가는게 맞을거같네요
[#197] TEST : Today Unit test code 작성
🌱 작업한 내용
🌱 PR Point
공통적으로 APIServiceStub을 사용
Unit test를 진행할 시에 고려해야하는
FIRST principle
이 존재합니다. 여기서F(Fast)
는 테스트는 빠르게 실행될 수 있어야함을 말하고,I(Isolated)
는 테스트들이 각각 독립적으로 수행되어야함을 말합니다.실제로 API 요청을 보내게 되면 네트워크 환경에 따라 속도가 매우 느려질 수 있으며, 실제 API 요청을 보내게 된다면 각 테스트들이 독립적이라고 할 수 없습니다. 따라서 가짜 객체를 return시켜주는 Stub 방식으로 테스트를 위한 APIService를 만들어서 테스트를 진행합니다.
#196
TodayManager Unit test
Manager의 책임
TodayManager의 책임은 API를 요청하고, 그 결과값을 앱 내에서 사용하기 위한 데이터인 AppData로 변환해서 ViewModel에게 리턴해주거나 API 요청 과정에서 에러가 발생했다면 에러를 전달하는 책임을 가지고 있습니다.
따라서 다음과 같은 테스트를 진행했습니다.
TodayViewModel Unit test
ViewModel의 책임
ViewModel은 Manager로부터 넘겨받은 데이터 혹은 에러를 그에 따른 적절한 작업을 Operator를 통해 수행하고 Output을 통해 ViewController에게 전달하는 책임을 가지고 있습니다.
따라서 다음과 같은 테스트를 진행했습니다.
이 때 Manager unit test를 통해 Manager의 로직을 검사하기 때문에, ViewModel를 테스트할 시에는 ManagerStub을 사용합니다.
TodayViewController Unit test
ViewController의 책임
TodayViewController는 user로부터 받는 action을 ViewModel에게 잘 전달해주고, Output stream을 observing하고 있다가 값이 변화면 UI에 데이터를 업데이트하는 책임을 가지고 있습니다.
따라서 다음과 같은 테스트를 진행했습니다.
테스트 방식
행동과 상태를 검증하는
TodayViewModelSpy
를 생성했습니다. ViewController에게 중요한 것은user action이 ViewModel로 잘전달이 되었는지
입니다.실제로 버튼 액션을 발생시키고 난 후에 ViewModel의 transform메서드에서 해당 event를 수신하는 시점에서 expectation fulfill을 해줘야하기 때문에 Output stream이 아닌 별도의 stream을 생성해서 해당 stream으로 이벤트를 전달합니다.
이를 ViewController test 코드 쪽에서 observing하고 있다가 이벤트를 받게 된다면(viewModel이 이벤트를 수신했다면)
expectation.fulfill()
메서드를 통해wait
을 빠져나갑니다.📸 스크린샷
📮 관련 이슈