테스트는 응용프로그램이 예상치 않은 동작을 했을 때만 실패하도록 해야 합니다. 응용 프로그램 코드가 무엇을 했는지를 테스트하는 것이지, 코드가 어떻게 되어있는지를 테스트하는 것이 아닙니다.
- 응용 프로그램이 무엇을 했는지를 확인하는 테스트를 **동작 테스트(behavioral tests)**라고 합니다.
- 동작이 동일하게 유지되더라도 응용 프로그램 코드가 변경되면 중단되는 테스트는 **취약한 테스트 (brittle tests)**입니다.
우리가 GorillaDB 라는 바나나 데이터베이스를 가지고 있다고 가정합시다.
GorillaDB 는 key-value로 바나나들을 저장하고 있습니다. 우리는 바나나를 다음과 같이 저장할 수 있습니다 :
let database = GorillaDB()
let banana = Banana()
database.save(banana: banana, key: "my-banana")그리고 나중에 디스크에서 바나나를 이렇게 불러올 수 있습니다 :
let banana = database.load(key: "my-banana")이 동작을 어떻게 테스트해야 할까요? 한 가지 방법은 바나나를 저장한 이후의 데이터베이스 크기를 확인하는 것입니다 :
// GorillaDBTests.swift
func testSave_savesTheBananaToTheDatabase() {
// Arrange: Create a database and get its original size.
let database = GorillaDB()
let originalSize = database.size
// Act: Save a banana to the database.
let banana = Banana()
database.save(banana: banana, key: "test-banana")
// Assert: The size of the database should have increased by one.
XCTAssertEqual(database.size, originalSize + 1)
}그러나 GorillaDB 의 코드가 변경된다고 상상해 보세요. 바나나를 데이터베이스에서 빠르게 읽을 수 있도록 만들려면 가장 자주 사용되는 바나나의 캐시를 유지해야 합니다. GorillaDB.size 의 크기는 캐시가 커짐에 따라 점차 커지고, 테스트는 실패할 것입니다.
동작 테스트 작성의 핵심은 애플리케이션 코드에 기대하는 동작을 명확하게 하는 것입니다.
testSave_savesTheBananaToTheDatabase 라는 테스트에서 : 우리가 바나나를 데이터베이스에 "저장" 할 때 우리가 기대하는 동작은 무엇일까요? "저장"이라는 것은 나중에 읽을 수 있다는 의미입니다. 따라서 데이터베이스의 사이즈가 증가하는 것을 테스트하는 것이 아니라, 바나나를 읽을 수 있는지를 테스트해야 합니다.
// GorillaDBTests.swift
func testSave_savesTheBananaToTheDatabase() {
// Arrange: Create a database and get its original size.
let database = GorillaDB()
- let originalSize = database.size
// Act: Save a banana to the database.
let banana = Banana()
database.save(banana: banana, key: "test-banana")
- // Assert: The size of the database should have increased by one.
- XCTAssertEqual(database.size, originalSize + 1)
+ // Assert: The bananas saved to and loaded from the database should be the same.
+ XCTAssertEqual(database.load(key: "test-banana"), banana)
}동작 테스트를 작성할 때 중요한 포인트 :
- 정확히 이 애플리케이션 코드가 무엇을 해야 하는지?
- 테스트가 오직 동작만을 테스트하는가? 또는 코드가 다르게 작동함에 따라 실패할 수 있는가?
