MVVM 토이 프로젝트- 3

Choooose·2023년 5월 20일
0

이전에 진행한 MVVM 토이 프로젝트를 활용하여 UnitTest를 수행했다.

테스트 코드를 작성하기 전에 UnitTest가 무엇인지 TDD 개발 프로세스는 무엇인지에 대해 정리해보았다.

TDD(Test-Driven Development) 란 ?

테스트 코드를 작성하면서 개발하는 테스트 주도 개발이다.

개발자는 먼저 요구사항을 검증하는 자동화된 테스트 케이스를 작성한다. 그런 후에, 그 테스트 케이스를 통과하기 위한 최소한의 코드를 생성한다. 마지막으로 작성한 코드를 표준에 맞도록 리팩토링한다. - 위키백과

반복적인 테스트를 통해 작은 단위의 테스트 코드를 작성하고 작성된 테스트 코드를 실제로 사용할 수 있도록 리팩토링하는 방식이다.

따라서 일반적인 개발방식과는 다르게 TDD는 실제 코드를 작성하기 전에

실패하는 테스트 코드테스트 코드를 성공시키는 최소한의 실제 코드실제 코드의 리팩토링

의 순서로 개발한다.

이 과정을 TDD Cycle이라 하며

위의 각 단계를 TDD에서는 Red, Green, Blue 단계라고 한다.

그렇다면 TDD를 통한 이점은 뭘까 ?

객체 지향적인 코드개발, 설계 수정 시간의 단축, 리팩토링의 편리함 등등 여러 이점이 있지만 단순하게 정리하면

하나의 테스트 코드를 작성하고 난 후의 실제 코드를 작성하기 때문에
정말 최소한의 모듈을 구동시키는 실제코드를 구현하게 될 것이고 그렇게 되면 소스코드가 간결해지고 각 코드의 의존성이 줄어든다는 점이다.

또한 새로운 모듈이 추가되어도 코드의 예외, 버그 사항이 줄어들게 된다.
(이미 추가된 모듈들이 모두 테스트코드를 거쳤기 때문)

추가적으로 유지보수 또한 편리해진다.
각 모듈의 의존성이 낮기 때문에 문제점을 쉽게 찾을 수 있고 하나의 모듈을 리팩토링하기에도 편리하다

단점은 개발 속도의 저하이다.

하나의 모듈을 추가할 때마다 바로 개발하는 것이 아닌 테스트 코드를 작성해야한다는 것은 큰 부담이다.
처음부터 실패하는 테스트 코드와 실제 코드 2가지의 코드를 짜야하기 때문이다.

또한 프로젝트에 도입하기 위해서는 필요한 지식을 습득해야한다. 또한 개발환경을 구축하는 것에도 시간이 많이 소모된다고 한다.

따라서 이러한 단점을 해소하기 위해서는 어느정도의 타협이 필요하다.
무조건 TDD를 개발 프로세스로 채택하는 것이 아닌 핵심 기능의 경우나 테스트 자동화 (CI) 등에서 활용하는 것이 좋은 방안이라고 한다.

UnitTest란 ?

TDD가 테스트 코드를 작성한 후에 개발하는 테스트 주도 개발 프로세스라면 UnitTest는 그 내부의 모듈을 테스트하는 절차를 의미한다.

유닛 테스트(unit test)는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말한다. - 위키백과

쉽게 말해 프로젝트의 여러 모듈(클래스, 메소드 등) 중 특정 모듈을 테스트하는 절차를 의미한다.

UnitTest 수행

실제로 저번에 진행한 프로젝트 ‘MVVM_ToyProject’를 가지고 UnitTest를 수행해보았다.

Xcode에서 UnitTest를 진행하기 위해서는 아래와 같이 프로젝트를 만들때 Include Tests 를 체크해주어야한다.

체크 후에 프로젝트를 생성하면

테스트 코드를 작성할 수 있는 .swift 파일이 추가된다.

그중 UITest가 아닌 Test에 들어가면 위와 같은 Swift 파일을 볼 수 있다.

XCTestCase 클래스는 TestCase, TestMethod, PerformanceTest를 정의할 수 있는 기본 클래스라고 할 수 있다.

클래스 내부의 메소드들은 테스트를 도와주는 메소드들이라고 할 수 있다.

먼저 setUpwithError() 메소드는 테스트를 하기 전에 모든 상태를 초기화 시켜주는 메소드이다.

다음으로 tearDownWithError() 메소드는 테스트가 끝나고 난 후의 리소스를 정리 시켜주는 메소드이다.

마지막으로 testPerformanceExample() 메소드는 테스트할 코드 블럭의 성능을 측정하는 메소드이다.

테스트 메소드 구현

https://github.com/TaekH/MVVM_ToyProject

저번에 진행한 MVVM 토이 프로젝트를 바탕으로 테스트 메소드를 만들어 보았다.

테스트 메소드 이름은 반드시 test로 시작해야한다.

또한 메소드의 구조는 given → when → then으로 작성하는 것이 좋다.

  • given : 테스트에 필요한 값들을 선언하는 단계
  • when : 테스트 코드를 실행하는 단계
  • then : 결과를 확인하는 단계

NewsViewModel에서 주어진 인덱스 매개변수에 따라서 ArticleViewModel을 리턴하는 articleIndex() 메소드를 테스트해보았다.

테스트를 하기전에 주의해야할 점은 하나의 기능만을 테스트한다는 것이다.

기존 프로젝트의 흐름은 네트워크 통신을 통해 내려받은 article 배열을 NewsViewModel이 하나의 article만 받아서 정제하는 ArticleViewModel로 반환하는 흐름이지만

반환을 성공적으로 하는지 만 테스트를 할 것이기 때문에 네트워크 통신은 같이 테스트하지않는다.

따라서 통신 후에 생길 데이터를 미리 mockNews 라는 임시 값으로 만들어주었다.

또 mockNews 데이터를 받아서 ArticleViewModel로 반환하기 위한 NewsViewModel을 구현해주었다.

let mockNews = [
        Article(author: "a", title: "b", description: "c", publishedAt: "2023-05-14T20:59:59Z"),
        Article(author: "a", title: "b", description: "c", publishedAt: "d"),
        Article(author: "a", title: "b", description: "c", publishedAt: "d")
        ]
let mockNewsVM = NewsViewModel(articles: mockNews)

위의 테스트를 위한 값을 구현해주는 과정이 given이 된다.

다음으로 테스트할 메소드인 articleIndex 메소드를 실행한다.

let result = mockNewsVM.articleIndex(0)

위의 과정이 테스트 코드 (메소드)를 실행하는 when 단계가 된다.

마지막으로 articleIndex() 메소드를 실행한 값이 들어있는 result 변수와 예상하는 값을 비교해준다.

XCTAssertEqual(result.author, "a")
XCTAssertEqual(result.title, "b")
XCTAssertEqual(result.description, "c")
XCTAssertEqual(result.publishedAt, "2023-05-14 20:59:59")

위 과정이 결과를 확인하는 then 단계가 된다.

여기서 XCTAssertEqual은 테스트 결과 값과 예상값이 같은지를 비교해주는 메소드로

같다면 UnitTest에 성공하게 된다.

XCTAssertEqual 이외에도 다양한 메소드를 통해 예상값과 결과값을 비교하여 테스트 성공 여부를 출력할 수 있다.
https://developer.apple.com/documentation/xctest/boolean_assertions

테스트를 수행하면 아래와 같이 성공하는 것을 확인할 수 있고 이를 통해 테스트한 기능이 정상적으로 동작한다는 것을 알 수 있다.

후기

이전까지는 특정 모듈을 테스트하기 위해서는 전체 빌드를 진행후에 테스트를 하거나 print문을 활용하였는데 이때마다 생겼던 문제점은
특정 모듈 테스트를 위해서 전체 빌드하는 것에 시간이 너무 오래걸린다는 점, 전체를 빌드 하고 특정 모듈을 테스트하기 때문에 다른 모듈들의 문제가 발생할 시에 찾기 힘들다는 점이었다.

그러나 MVVM이라는 아키텍처 패턴과 XCTest를 활용한 UnitTest를 진행한 결과, 구조와 설계가 잘 잡힌 코드라면 UnitTest를 활용하는 방법이 이후 유지보수 측면이나 개발 중간의 테스트 과정에서 편리한 것 같다.

또한 부분적으로 TDD를 활용하는 방법 ( 핵심 기능 개발 등의 상황에서 ) 또한 시도해봐도 좋을 것 같다.

참조


XCTestCase | Apple Developer Documentation

https://hanamon.kr/tdd란-테스트-주도-개발/

https://sujinnaljin.medium.com/swift-mock-을-이용한-network-unit-test-하기-a69570defb41

https://silver-g-0114.tistory.com/142

0개의 댓글