소스 코드의 특정 모듈이 의도대로 작동하는지 검증하는 절차
= 모든 함수와 메서드에 대한 테스트 케이스(Test case)를 만드는 절차
유닛 테스트는 다른 말로 단위 테스트라고 한다. 하나의 함수, 메서드를 기준으로 진행되는 가장 작은 단위틔 테스트이다. -> 메서드를 하나 하나 테스트해보는 개념
단위 테스트보다 큰 단위로 주로 객체 사이의 동작에 대한 테스트
UI에 대한 사용성을 테스트하는 것인데 비산 비용과 실제 사용성과 차이가 있어 많이 사용되지는 않는다.
예상 값
과 결과 값
을 비교하는 방식으로 진행
! 테스트 가능한 코드를 짜는 것도 중요 (안되는 경우 예시 - 의존성이 너무 강해 메서드 외부 코드의 영향을 매우 많이 받는 경우)
Bool
을 이용해 스스로 성공/실패 검증이 가능해야 한다.info.plist
가 새로 생성됨(Xcode 13 버전 이후로는 별도로 생성되지 않고 Target 세팅에 숨겨져 있음)
info.plist
: 실행 패키지에 관한 필수 설정 정보가 포함된 구조화된 텍스트 파일
import XCTest
: 유닛 테스트, 퍼포먼스 테스트, UI 태스트를 만들고 실행하는 프레임워크XCTest
: 테스트의 기본이 되는 추상 클래스XCTestCase
: XCTest의 하위 클래스로 테스트를 작성하기 위해 상속하는 클래스 -> 테스트를 위한 다양한 프로퍼티와 메서드를 사용할 수 있음setUpWithError()
: 테스트가 같은 상태와 조건에서 실행할 수 있도록 테스트 케이스가 실행되기 전에 호출되는 메서드tearDownWithError()
: 각 테스트의 실행이 끝난 후 호출되는 메서드testExample()
: 테스트 케이스가 되는 메서드(test로 시작하는게 일반적이며 문서화를 위해 한글로 짓기도 함)testPerformanceExample()
: 성능을 테스트하기 위한 메서드, measure(block:)
메서드를 통해 성능 측정@testable import 파일이름
@testable
: 앱 타겟에 있는 코드에 접근하기 위한 키워드setUpWithError()
에서 프로퍼티 초기화tearDownWithError()
에서 다시 nil
로 초기화super
를 불러오는 이유 = XCTestCase
를 상속받아 메서드롤 override
해서 사용하기 때문에테스트 결과를 확인하는 함수
XCTAssertEqual
: 비교하는 두 값이 같은지 확인하는 함수XCTAssertGreaterThan
: 대소 비교XCTAssertNil
:nil
인지 판별XCTAssertThrowsError
: 무엇을throw
하는지XCTAssertTrue
,XCTAssertFalse
: 반환 된Bool
타입
Command + U
실제 앱 코드에서 테스트가 어느 정도 진행되었는지 알 수 있는 툴
= 테스트의 가치를 측정해주는 툴
Product -> Scheme - Edit Schemev - Test - Options - Code Coverage 활성화
이후Report
네이베이션에서Test log
에서Coverage
선택
불가능하다. 값은 무작위하게 결정되므르 기대 값과 예상 값을 설정할 수 없기 때문이다.
URLSession
을 통해 랜덤 값을 받아오는 메서드일 때 테스트 방식은?
-> 메서드를 호출하고 랜덤 값과 비교해 범위 내에 있는지 확인하면 되나?
-> ❌ 테스트 결과 함수를 아예 실행하지 않고 지나감
-> 비동기적으로 처리하는 메서드이기 때문!!
expectation(description:)
: 수행되어야 하는 내용을 description으로 정해줌fulfull()
: 정의한expectation
가 충족될 때 호출wait(for:timeout:)
:expectation
을 배열로 전달해 배열의 모든 요소가fulfill
이 될 때까지 기다린다.timeout
으로 시간을 제한할 수 있음
여러 비동기 작업을 기다려야 한다면 여러 개의 expectation
을 만들어 기다릴 수 있다.
이전에 했던 방식은 네트워크 환경이 구축된 상태에서만 가능하다.
-> Respeatable 원칙을 벗어남
하지만 메서드가 네트워크를 통해 동작하는데 어떻게 네트워크 없이 테스트를 할까?
-> 테스트 객체를 만들어서 해결
테스트를 진행하기 어려운 경우 대신해서 테스트할 수 있도록 만드는 객체
실제 객체를 테스트 더블로 바꿔서 테스트를 진행한다. -> 마치 스턴트 배우가 대신 해주듯이!
- 테스트 대상 코드를 격리
- 테스트 속도 개선
- 예측 불가능한 실행 요소 제거
- 특수한 상황을 시뮬레이션
- 감춰진 정보를 얻음
1) Dummy
2) Stub
3) Fake
4) Spy
5) Mock
하나의 객체가 다른 객체의 의존성을 제공하는 기술
어떤 객체가 내부에서 생성해 가지고 있는 객체
내부에서 초기화되지 않고 외부에서 객체를 생성하여 내부에 주입시키는 방식
객체간의 결합도를 낮추기 위해
네트워크 이용(원래)
URLSession -> datatask -> URLSessionDataTask -> resume -> Nestworking -> completion Handler
- URLSession Data Task를 만들어 네트워킹을 통해 값을 얻어와 completion Handler를 실행
Test Double
DummyData -> StubURLSession -> datatask(DummyData) -> Stub URLSessionDataTask -> resume -> completion Handler
- 네트워킹으로 받아오는 대신 직접 Data를 만들어 completion Handler에 전달
- URLSession와 URLSessionDataTask대신 DummyData를 전달할 수 있는 Stub객체로 바꿔치기
미리 request에 대한 답을 설정해두고 전달하는 방식으로 테스트를 진행
FIRST 원칙에서 Timely에 따르면 테스트는 실제 코드 구현 직전에 구현해야한다고 한다. 아직 메서드가 구현되지 않았는데 어떻게 테스트를 구현할 수 있을까?
이 말은 테스트를 작성하면서 동시에 메서드를 구현해간다는 의미이다. 이러한 테스트 방법론을 TDD(Test-Driven Development)
라고 한다.
테스트를 작성하면서 코드를 완성시키는 방법론
1) 요구사항을 검증하는 자동화된 테스트 케이스 작성
2) 테스트 케이스를 통과하는 최소한의 코드 생성
3) 코드를 표준에 맞게 리팩터링
- Red : 실패하는 테스트 작성 구간
- Green : 실패하는 테스트를 최소한의 변경으로 성공하게 하는 구간
- Refactor : 테스트의 성공을 유지하며 개선하는 구간
참고: 야곰닷넷 - Unit Test