You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classCashRegisterTests:XCTestCase{func testInit_setsDefaultAvailableFunds(){
// when
letsut=CashRegister()
// then
XCTAssertEqual(sut.availableFunds,0)}func testInitAvailableFunds_setsAvailableFunds(){
// given
letavailableFunds=Decimal(100)
// when
letsut=CashRegister(availableFunds: availableFunds)
// then
XCTAssertEqual(sut.availableFunds, availableFunds)}func testAddItem_oneItem_addsCostToTransactionTotal(){
// given
letavailableFunds=Decimal(100)letsut=CashRegister(availableFunds: availableFunds)letitemCost=Decimal(42)
// when
sut.addItem(itemCost)
// then
XCTAssertEqual(sut.transactionTotal, itemCost)}}
하나씩 자세히 살펴보면 testInitAvailableFunds_setsAvailableFunds와 testAddItem_oneItem_addsCostToTransactionTotal 두가지 메소드는availableFunds와 CashRegister를 사용하고 있는 것을 볼 수 있다. 이는 클래스 프로퍼티로 빼줄 수 있다.
위와 같이 프로퍼티로 빼게 될경우, setup과 teardown 메소드를 이용해서 초기화해줄 수 있다.
setup() : 테스트 메소드가 동작하자마자 호출되는 메소드 (before)
tearDown() : 각 테스트 메소드가 불리우자마자 호출되는 메소드 (after)
overridefunc setUp(){
super.setUp()
availableFunds =100
sut =CashRegister(availableFunds: availableFunds)}overridefunc tearDown(){
availableFunds =nil
sut =nil
super.tearDown()}
tearDown메소드에서 nil처리를 하는 이유는 XCTestCase를 서브클래싱하는 클래스는 내부의 테스트 케이스가 모두 끝날때까지 프로퍼티를 가지고 있는다. 프로퍼티의 메모리를 계속 유지하고 있기 때문에 테스트코드를 돌릴 때 메모리와 성능 이슈가 생길 수 있다. 따라서 각 테스트 케이스가 끝나는 시점에 메모리에서 릴리즈해준다.
setUpWithErrortearDownWithError 메소드는 setup, tearDown할 때 오류가 날 수 있는 경우에 사용한다.
func testInitAvailableFunds_setsAvailableFunds(){
// when
letsut=CashRegister(availableFunds: availableFunds)
// then
XCTAssertEqual(sut.availableFunds, availableFunds)}func testAddItem_oneItem_addsCostToTransactionTotal(){
// given
letitemCost=Decimal(42)
// when
sut.addItem(itemCost)
// then
XCTAssertEqual(sut.transactionTotal, itemCost)}}
프로퍼티를 밖으로 빼면 테스트 함수가 간단해진다.
4️⃣ Repeat : 다시 반복하자
Basic Concept
1. 테스트 메소드 네이밍 규칙
test 로 시작
테스트할 것을 작성 ex) testInit
언더바로 뒤에는 필요한 조건들을 작성 ex) testAdd_Int타입만 작성이 가능
마지막으로, 나오는 결과를 작성 ex) testInit_create객체명
2. 컴파일 실패 또한 테스트 실패로 간주
3. Refactor할 때 규칙
Duplicate logic : 프로퍼티와 메소드 클래스를 만들어 반복되는 코드를 제거하자
Comments : "어떻게" 보다는 "왜"에 초점을 맞추어 작성
// for문을 돌면서 매번 status을 확인하여 반환 (x)
// status가 모두 true일 경우, 상태가 완료된 것으로 간주하여 true를 반환 (o)
Code smells : Class와 Method를 만들고 코드를 리네이밍과 재구조하면서 냄새나는 코드 제거
4. Give/When/Then
Given a certain conditions...
When a certain action happens...
Then an expected result occurs
func testInitAvailableFunds_setsAvailableFunds(){
// given
letavailableFunds=Decimal(100)
// when
letsut=CashRegister(availableFunds: availableFunds)
// then
XCTAssertEqual(sut.availableFunds, availableFunds)}
위 코드를 해석해보면, 100인 avaiableFunds가 주어졌고 (given) init(availableFunds:)를 통해 초기화한 sut가 생성된 상황이면 (when) sut의 avaiableFunds와 availableFunds는 같다. (then)
sut는 무슨 약자?
system under test
정리
단계 : 실패하는 코드를 먼저 작성 -> 테스트 통과되게 코드를 작성 -> 리팩토링 -> 반복하기
given / when / then : 주어진 상황 속에서 어떤 액션이 주어지고 예상한 결과가 일어난다.
setup(), tearDown() : XCTest를 서브클래싱하는 클래스내에 존재하는 메소드, setup을 통해 각 테스트 케이스가 동작할 때 클래스 프로퍼티를 초기화하고, tearDown을 통해 각 테스트케이스마다 프로퍼티를 해제하여 메모리와 성능 이슈 방지를 방지한다.
완성된 테스트 코드 예제
import XCTest
@testableimport TDDPractice
classCashRegisterTests:XCTestCase{varavailableFunds:Decimal!varsut:CashRegister!varitemCost:Decimal!overridefunc setUp(){
super.setUp()
availableFunds =100
sut =CashRegister(availableFunds: availableFunds)
itemCost =Decimal(42)}overridefunc tearDown(){
availableFunds =nil
sut =nil
itemCost =nil
super.tearDown()}func testInit_setsDefaultAvailableFunds(){
// when
letsut=CashRegister()
// then
XCTAssertEqual(sut.availableFunds,0)}func testInitAvailableFunds_setsAvailableFunds(){
// when
letsut=CashRegister(availableFunds: availableFunds)
// then
XCTAssertEqual(sut.availableFunds, availableFunds)}func testAddItem_oneItem_addsCostToTransactionTotal(){
// when
sut.addItem(itemCost)
// then
XCTAssertEqual(sut.transactionTotal, itemCost)}func testAddItem_twoItems_addsCostsToTransactionTotal(){
// given
letitemCost=Decimal(20)letexpectedTotal= itemCost
// when
sut.addItem(itemCost)
// then
XCTAssertEqual(sut.transactionTotal, expectedTotal)}}
The text was updated successfully, but these errors were encountered:
Chapter 2 The TDD Cycle
레이먼드 아저씨 책 - iOS Test-Driven Development by Tutorials 의 두번째 챕터 TDD Cycle에서 배운 내용
TDD는 아주 간단한 프로세스로 이루어진다.
Red-Green-Refactor-Repeat (RGRR)
각 단계에서 어떤 작업이 필요한지 하나씩 예제를 통해 보자.
Example
1️⃣ Red : 실패하는 코드 작성하기
CashRegister 클래스를 초기화하는 테스트코드를 작성하자.
2️⃣ Green : 테스트를 성공하게 만들기
CashRegister클래스를 작성하여 성공하게 만들자.
3️⃣ Refactor: 코드 정리하기
아래의 테스트 코드가 있다고 해보자.
하나씩 자세히 살펴보면
testInitAvailableFunds_setsAvailableFunds
와testAddItem_oneItem_addsCostToTransactionTotal
두가지 메소드는availableFunds
와CashRegister
를 사용하고 있는 것을 볼 수 있다. 이는 클래스 프로퍼티로 빼줄 수 있다.위와 같이 프로퍼티로 빼게 될경우,
setup
과teardown
메소드를 이용해서 초기화해줄 수 있다.setup()
: 테스트 메소드가 동작하자마자 호출되는 메소드 (before)tearDown()
: 각 테스트 메소드가 불리우자마자 호출되는 메소드 (after)tearDown메소드에서 nil처리를 하는 이유는 XCTestCase를 서브클래싱하는 클래스는 내부의 테스트 케이스가 모두 끝날때까지 프로퍼티를 가지고 있는다. 프로퍼티의 메모리를 계속 유지하고 있기 때문에 테스트코드를 돌릴 때 메모리와 성능 이슈가 생길 수 있다. 따라서 각 테스트 케이스가 끝나는 시점에 메모리에서 릴리즈해준다.
setUpWithError
tearDownWithError
메소드는 setup, tearDown할 때 오류가 날 수 있는 경우에 사용한다.프로퍼티를 밖으로 빼면 테스트 함수가 간단해진다.
4️⃣ Repeat : 다시 반복하자
Basic Concept
1. 테스트 메소드 네이밍 규칙
test
로 시작testInit
testAdd_Int타입만 작성이 가능
testInit_create객체명
2. 컴파일 실패 또한 테스트 실패로 간주
3. Refactor할 때 규칙
Duplicate logic : 프로퍼티와 메소드 클래스를 만들어 반복되는 코드를 제거하자
Comments : "어떻게" 보다는 "왜"에 초점을 맞추어 작성
Code smells : Class와 Method를 만들고 코드를 리네이밍과 재구조하면서 냄새나는 코드 제거
4. Give/When/Then
위 코드를 해석해보면, 100인
avaiableFunds
가 주어졌고 (given) init(availableFunds:)를 통해 초기화한 sut가 생성된 상황이면 (when) sut의 avaiableFunds와 availableFunds는 같다. (then)정리
setup()
,tearDown()
: XCTest를 서브클래싱하는 클래스내에 존재하는 메소드, setup을 통해 각 테스트 케이스가 동작할 때 클래스 프로퍼티를 초기화하고, tearDown을 통해 각 테스트케이스마다 프로퍼티를 해제하여 메모리와 성능 이슈 방지를 방지한다.완성된 테스트 코드 예제
The text was updated successfully, but these errors were encountered: