9.1 유닛 테스트

앞서 Dependency에 대해 깊이 알아본 이유는 각종 의존성을 효율적으로 안전하게 관리하기 위함입니다. 결과적으로 개발자들은 각 의존성의 동일성을 해치지 않고 안전하게 사용할 수 있게 되었습니다. 이는 앞서 살펴본 audioPlayer의 예시처럼 여러 로직을 보관하는 인스턴스를 경우에 알맞게 활용하고 호출하는 방식으로도 사용이 가능합니다. TCA는 테스트 또한 마치 부품과 같이 store, 또 그 안의 reducer, 그 속의 action 단위로 원하는 상황을 상정하여 테스트하기에 정말 용이합니다. 심지어 의존성을 배제하여 실제로 통신을 하지 않는 테스트도 진행할 수 있습니다. 즉, 지금까지 책에서 다룬 모든 내용을 테스트하기 위한 편의를 제공하고 있으며, 이를 유닛 테스트에 적용한다면 더 안정적이고 빠른 테스트를 진행할 수 있습니다.

이제부터 TCA의 가장 큰 장점 중 하나인 빠르고 편리한 테스트에 대해 알아보겠습니다.


9.2 TCA와 Testable Code

지금까지의 챕터에서 살펴보았듯, TCA는 State를 변형하는 특정 Action을 열거하여 정의하는 방식으로 어플리케이션의 상태를 제어합니다. 각 상태의 변형은 Action에 의한 변형을 주관하는 Reducer가 그 책임을 갖고 있으며, 각 Reducer는 서로 독립적입니다. 그럼에도 불구하고 .ifLet(), .forEach() 등의 Reduce 메소드의 도움으로 각 Reducer는 다른 Reducer와 유기적으로 관계를 맺을 수 있습니다. 그렇다면 기능을 구현할 때, 개발자는 다음과 같은 사항들을 고려해야 합니다.

  1. State가 의도한대로 변형되는지
  2. 각 Reducer의 State, Action이 원활하게 전달되고 있는지
  3. 특정 Action을 트리거할 때, 다른 Action이 제대로 피드백 되는지

TCA의 테스트 코드는 각 Action을 직접 트리거하고 해당 Action이 야기하는 변형을 State에 직접 할당하여 비교하는 방식으로 작성합니다. 개발자가 테스트할 때 할당하는 State 값이 실제 State 값과 다르다면 테스트는 실패하며, 관련 정보를 Log로 확인할 수 있습니다. 또한 트리거된 Action이 다른 Action을 피드백할 때, 관련 동작을 처리하지 않더라도 테스트는 실패합니다. 이와 관련된 자세한 설명은 추후 챕터에서 살펴보겠습니다.

9.2.1 TCA가 지향하는 Testable Code

*하단의 내용은 TCA를 적용한 SwiftUI와 기능별 Unit Test를 중심으로 작성되었으며, 테스트 코드에 대한 전반적인 내용은 생략되어 있습니다.

TCA 공식 레포지토리에서 밝히듯, TCA를 적용한 SwiftUI 클라이언트를 개발한다면 테스트 코드를 기능별로 효율적으로 작성할 수 있습니다. TCA가 지향하는 테스트 코드에 능숙해진다면 아래의 이점을 가져갈 수 있습니다.