Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] TDD (Test Driven Development) 본문

Unit Test와 UI Test

[iOS - swift] TDD (Test Driven Development)

jake-kim 2021. 2. 12. 00:38

TDD

  • 테스트 주도 개발
  • Unit test구조가 잡혀있으면 추후에 리팩토링 후 확인이 쉬워, 변경이 쉬움 -> unit test구조를 먼저 잡기위해 TDD방법 존재
  • 보통 기획서가 있으면, 그 기획서에 나와있는 내용들을 테스트케이스로 만들며 개발
  • 협업 - 개발자 한명은 테스트를 작성, 나머지는 테스트를 통과하는 코드를 작성

TDD 사용

  • Red-Green-Refactor
    - Red: 테스트가 실패하는 코드 작성 (실패를 확인)
    - Green: 테스트를 통과하기위한 최소한의 구현
    - Refacrtor: 코드를 정리하고 최적화

TDD 준비

  • Numero 코드 - 숫자와 로마 숫자 맞추기 (플레이어가 맞는지 체크 -> 10번 시도)

  • Unit Test Case Class파일 생성

  • 세팅
    - 디바이스는 simulator로 수정
    - @testable import Numero
    - func testConversionForOne() 함수 추가
    - converter객체 생성

TDD 사용

  • 개발목적: 숫자를 로마 숫자로 변환하는 convert모듈 생성
  • Red: 틀린 테스트 케이스 작성
func testConversionForOne() {
    let result = converter.convert(1) // convert라는 함수가 존재하지 않으므로 컴파일에러
}
  • Green: 테스트를 통과하기 위한 코드 작성 (Convert 클래스에 convert함수 작성)

비어있는 Converter 클래스

class Converter {
    func convert(_ number: Int) -> String {
        return ""
    }
}
  • Red: (반환 값에관한 결과에 틀린값 입력)
func testConversionForOne() {
    let result = converter?.convert(1)
    XCTAssertEqual(result, "I", "1에 관한 convert결과 틀림")
}

  • Green: convert(_:)함수 테스트 코드 통과하기 위한 최소한의 수정

 

class Converter {
    func convert(_ number: Int) -> String {
        return "I" // ""에서 "I"로 수정
    }
}
  • 테스트 통과 확인 - 단축키 "cmd + U"

  • Red: 다른 테스트 코드 작성
func testConversionForTwo() {
    let result = converter?.convert(2)
    XCTAssertEqual(result, "II", "2에 관한 convert결과 틀림")
}
  • Green: convert(_:)함수 테스트 코드 통과하기 위한 최소한의 수정
// 입력한 개수만큼 "I"를 반복하여 반환하도록 수정

class Converter {
    func convert(_ number: Int) -> String {
        return String(repeating: "I", count: number)
    }
}
  • 테스트 통과 확인

  • Red: 다른 틀리는 케이스 작성
func testConversionFive() {
    let result = converter?.convert(5)
    XCTAssertEqual(result, "V", "5에 관한 convert결과 틀림")
}
  • Green: converter함수를 테스트 코드 통과하기 위한 최소한의 수정
class Converter {
    func convert(_ number: Int) -> String {
        if number == 5 {
            return "V"
        } else {
            return String(repeating: "I", count: number)
        }
    }
}
  • 통과 확인

  • Red: 틀린 테스트 코드 작성
func testConversionForSix() {
    let result = converter?.convert(6)
    XCTAssertEqual(result, "VI", "6에 관한 convert결과 틀림")
}
  • Green: convert(_:)에 테스트를 통과하는 최소한의 코드 수정
class Converter {
    func convert(_ number: Int) -> String {
        var result = ""
        var localNumber = number
        if localNumber >= 5 {
            result += "V"
            localNumber = localNumber - 5
        }
        result += String(repeating: "I", count: localNumber)
        return result
    }
}
  • 통과 확인

  • Red: 틀린 테스트 케이스 작성
func testConversionForTen() {
    let result = converter?.convert(10)
    XCTAssertEqual(result, "X", "10에 관한 convert결과 틀림")
}
  • Green: 테스트를 통과하는 최소한의 코드 작성
class Converter {
    func convert(_ number: Int) -> String {
        var result = ""
        var localNumber = number
        if localNumber >= 10 {
            result += "X"
            localNumber -= 10
        }
        if localNumber >= 5 {
            result += "V"
            localNumber = localNumber - 5
        }
        result += String(repeating: "I", count: localNumber)
        return result
    }
}
  • Red: 패턴을 알아내기 위해서 다른 테스트 코드 작성
func testConversionForTwenty() {
    let result = converter?.convert(20)
    XCTAssertEqual(result, "XX", "20에 관한 convert결과 틀림")
}

  • "XCIIIII"결과를 확인 후 Green
if localNumber >= 10 {
while localNumber >= 10 {
  • 테스트 확인

  • Red: 특별한 테스트 케이스 처리
func testConversionForFour() {
    let result = converter?.convert(4)
    XCTAssertEqual(result, "IV", "4에 관한 convert결과 틀림")
}

  • Green - "I"를 반복하여 추가하는 구문 앞에 아래 코드 추가
if localNumber >= 4 {
    result += "IV"
    localNumber -= 4
}

  • Res: 9에관한 테스트 케이스
func testConversionForNine() {
    let result = converter?.convert(9)
    XCTAssertEqual(result, "IX", "9에 관한 convert결과 틀림")
}

  • Green - 10과 5를 처리하는 코드 사이에 다음을 추가
if localNumber >= 9 {
    result += "IX"
    localNumber -= 9
}

  • Refactor: 기존 코드를 리펙토링 (생략)
    - 중복코드가 존재하면 함수로 생성
    - 코드 최적화

 

* 참고: www.raywenderlich.com/5522-test-driven-development-tutorial-for-ios-getting-started

 

Comments