클린 코드 적용기 - 깨끗한 테스트코드

유재경·2022년 5월 27일
0

Clean Code 적용기

목록 보기
4/4

(※ 실제 코드 유출 방지를 위해 약간의 코드 변형을 하였습니다.)

깨끗한 테스트 코드를 작성하라

  • 첫째도 가독성, 둘째도 가독성
  • 코드가 수정되면 테스트 코드도 수정되어야 한다. 그럴 때마다 테스트 코드가 지저분하다면? 테스트 코드를 수정하는 시간이 길어질 것이다.

테스트 코드 함수 당 하나의 결과만 체크하자

  • 한 가지 케이스에 대한 결과만을 체크하자
  • FIRST 규칙을 따르자
    • F(Fast): 테스트는 빨리 돌아야 한다. 그래야 자주 체크할 수 있다.
    • I(Independent): 테스틑 독립적이어야 한다. 한 테스트가 다음 테스트가 실행될 환경을 준비해서는 안된다.
    • R(Repeatable): 어느 환경에서도 반복적으로 실행될 수 있어야 한다.
    • S(Self-Validating): 테스트는 Bool결과 값으로 나타나야 하며 수작업으로 비교해서는 안 됨
    • T(Timely): 적시에 실행되어야 한다.

Bad Practice

func testConfigureIntroButton() {
    let config1 = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: true, MMButtonFocused: true)
    viewModel.configureMMInfo(config1)
    
    var startButton = JoinLoginButton(type: .start, focused: false)
    var MMQRButton = JoinLoginButton(type: .MMQR, focused: true)
    let exp1: [JoinLoginButton] = [startButton, MMQRButton]
    XCTAssertEqual(viewModel.introButtonList, exp1)
    
    let config2 = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: true, MMButtonFocused: false)
    viewModel.configureMMInfo(config2)
    
    startButton = JoinLoginButton(type: .start, focused: true)
    MMQRButton = JoinLoginButton(type: .MMQR, focused: false)
    let exp2: [JoinLoginButton] = [startButton, MMQRButton]
    XCTAssertEqual(viewModel.introButtonList, exp2)
    
    let config3 = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: false, MMButtonFocused: false)
    
    viewModel.configureMMInfo(config3)
    
    startButton = JoinLoginButton(type: .start, focused: true)
    let exp3: [JoinLoginButton] = [startButton]
    XCTAssertEqual(viewModel.introButtonList, exp3)
}

문제점

  1. 하나의 테스트 코드 함수에 여러가지 케이스를 비교하고 있다.
  2. 여러가지 케이스를 테스트하기 위해 startButton이라는 변수에 계속해서 할당해서 사용하고 있다.

Good Practice

func testSetButtonMMEnabledAndFocused() {
    let config = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: true, MMButtonFocused: true)
    viewModel.configureMMInfo(config)
    
    let startButton = JoinLoginButton(type: .start, focused: false)
    let MMQRButton = JoinLoginButton(type: .MMQR, focused: true)
    let exp: [JoinLoginButton] = [startButton, MMQRButton]
    XCTAssertEqual(viewModel.introButtonList, exp)
}

func testSetButtonMMEnabledAndNotFocused() {
    let config = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: true, MMButtonFocused: false)
    viewModel.configureMMInfo(config)
    
    let startButton = JoinLoginButton(type: .start, focused: true)
    let MMQRButton = JoinLoginButton(type: .MMQR, focused: false)
    let exp: [JoinLoginButton] = [startButton, MMQRButton]
    XCTAssertEqual(viewModel.introButtonList, exp)
}

func testSetButtonMMNotEnabled() {
    let config = ServerConfig.MMConfig(imageUrl: "imageUrl", warningMessage: "유의사항", MMEnabled: false, MMButtonFocused: false)

    viewModel.configureMMInfo(config)
    
    let startButton = JoinLoginButton(type: .start, focused: true)
    let exp: [JoinLoginButton] = [startButton]
    XCTAssertEqual(viewModel.introButtonList, exp)
}

변경점

  1. 테스트해야할 케이스마다 각각의 테스트 코드 함수를 작성하여 가독성도 높이고 테스트 코드 작성 취지에 알맞게 변경되었다.
  2. 테스트 케이스 분리하여 작성함으로써 동일한 변수에 재할당하여 사용하는 일이 없어 테스트 결과에 영향을 줄 수 있는 side-effect를 줄였다.

회고

초반에 테스트 코드를 작성해야 하는 규칙을 몰랐을 때에는 하나의 테스트 함수에 모든 것을 담으려 했다. 최대한 테스트 케이스를 분리하여 작성하도록 명심해야겠다.

profile
iOS 개발

0개의 댓글