π μλ‘
μ¬λ¬ μΈμ μ΄λ μ±μ©κ³΅κ³ λ₯Ό 보면 λ¨μ ν μ€νΈμ λν μ΄μΌκΈ°λ₯Ό λ§μ΄ μ ν μ μλ€.
ν μ€νΈνλ©° μ½λ©μ νλ©΄ μ μ§λ³΄μκ° μ©μ΄νκ³ μ½λ μμ μ±μ λμ΄λ λ± λ€μν μ₯μ μ΄ μλ€.
μ¬ν ν μ€νΈμ μ€μμ±μ λν΄ μ μκ³ μμμ§λ§, λ΄ νλ‘μ νΈμλ μ μ©ν΄λ³΄μ§ λͺ»νλ€. κ·Έλμ νλ² μμΈνκ² νλ³΄κ³ μ μ 리ν΄λ³΄λ €κ³ νλ€.
βUnit Testμ λν΄
μ μ
μ»΄ν¨ν° νλ‘κ·Έλλ°μμ μμ€ μ½λμ νΉμ λͺ¨λμ΄ μλλ λλ‘ μ νν μλνλμ§ κ²μ¦νλ μ μ°¨
μ¦, λͺ¨λ ν¨μμ λ©μλμ λν ν μ€νΈ μΌμ΄μ€λ₯Ό μμ±νλ μ μ°¨λ₯Ό λ§νλ€. μ΄λ₯Ό ν΅ν΄μ μΈμ λΌλ μ½λ λ³κ²½μΌλ‘ μΈν΄ λ¬Έμ κ° λ°μν κ²½μ°, λ¨μκ° λ΄μ μ΄λ₯Ό νμ νκ³ λ°λ‘ μ‘μ μ μλλ‘ ν΄μ€λ€. μ΄μμ μΌλ‘ ν μ€νΈ μΌμ΄μ€λ λΆλ¦¬λμ΄μΌ νλ€. μ΄λ₯Ό μν΄ κ°μ§ κ°μ²΄(Mock object)λ₯Ό μμ±νλ κ²λ μ’μ λ°©λ²μ΄λ€. μ λ ν μ€νΈλ κ°λ°μ λΏλ§ μλλΌ λ³΄λ€ λ μ¬λμλ ν μ€νΈλ₯Ό μν΄ ν μ€ν°μ μν΄ μνλκΈ°λ νλ€.
- μν€ λ°±κ³Ό -
νλ μ΄μ
- ν΄λΉ λΆλΆ(ν¨μ, λ©μλ)μ λν΄μ λ 립μ μΌλ‘ ν μ€νΈλ₯Ό νκΈ° λλ¬Έμ λΉ λ₯Έ 리ν©ν λ§ λ°μκ³Ό λΉ λ₯Έ ν μ€νΈλ₯Ό μ§νν μ μλ€.
- μ½λμ νμ₯μ΄λ 리ν©ν λ§ μμλ μμ μ±μ ν보ν μ±λ‘ λΉ λ₯΄κ² λμν μ μλ€.
λ°©λ²
λμ νμ
- ν΅μ¬ κΈ°λ₯ : λͺ¨λΈ ν΄λμ€ λ° λ©μλ / 컨νΈλ‘€λ¬μμ μνΈμμ©
- κ°μ₯ μΌλ°μ μΈ UI μν¬ νλ‘
- κ²½κ³ μ‘°κ±΄
- λ²κ·Έ μμ
ν μ€νΈ κΈ°μ€ (FIRST μμΉ)
ν¨κ³Όμ μΈ λ¨μ ν μ€νΈλ₯Ό μν κ°κ²°ν κΈ°μ€ μΈνΈ
- Fast
- ν μ€νΈκ° λΉ λ₯΄κ² μ§νλμ΄μΌ νλ€.
- μλ§μ ν μ€νΈ μ½λλ₯Ό μμ±ν ν λ° ν ν μ€νΈκ° λλ¦¬κ² λμνλ©΄ λ무 μ€λκ±Έλ¦°λ€.
- Independent/Isolated
- κ°κ°μ ν
μ€νΈλ μλ‘ λ
립μ μ΄λ©° μμ‘΄ν΄μλ μλλ€.
- ν μ€νΈλ μλ‘ μνλ₯Ό 곡μ ν΄μλ μλλ€.
- μμ‘΄μ±μ΄ λμΌλ©΄ ν μ€νΈμ μμΈμ μ°ΎκΈ° μ΄λ €μμ§λ€.
- κ°κ°μ ν
μ€νΈλ μλ‘ λ
립μ μ΄λ©° μμ‘΄ν΄μλ μλλ€.
- Repeatable
- ν μ€νΈλ₯Ό μ€νν λλ§λ€ λμΌν κ²°κ³Όλ₯Ό μ»μ΄μΌ νλ€.
- ν΅μ νκΈ° μ΄λ €μ΄ λΆλΆμ ν μ€νΈλ₯Ό μν κ°μ²΄λ₯Ό λ§λ€μ΄μ£Όλ λ°©λ²λ μλ€.
- μΈλΆ λ°μ΄ν° 곡κΈμ λλ λμμ± λ¬Έμ λ‘ μΈν΄ κ°νμ μΈ μ€λ₯κ° λ°μν μ μλ€.
- Self-validating
- ν μ€νΈλ μμ μλνλμ΄μΌ νλ€.
- μΆλ ₯μ λ‘κ·ΈνμΌμ λν νλ‘κ·Έλλ¨Έμ ν΄μμ μμ‘΄νμ§ μκ³ βpassβ λλ βfailβ μ¬μΌ νλ€.
- Timely
- μ΄μμ μΌλ‘λ ν
μ€νΈνλ νλ‘λμ
μ½λλ₯Ό μμ±νκΈ° μ μ ν
μ€νΈλ₯Ό μμ±ν΄μΌ νλ€. μ΄λ₯Ό ν
μ€νΈ μ£Όλ κ°λ°μ΄λΌκ³ νλ€. (TDD)
- (μ΄κ² κ·Έ μ λͺ ν TDD?β¦)
- μ΄μμ μΌλ‘λ ν
μ€νΈνλ νλ‘λμ
μ½λλ₯Ό μμ±νκΈ° μ μ ν
μ€νΈλ₯Ό μμ±ν΄μΌ νλ€. μ΄λ₯Ό ν
μ€νΈ μ£Όλ κ°λ°μ΄λΌκ³ νλ€. (TDD)
π€ Xcodeμμμ UnitTest
νλ‘μ νΈλ₯Ό λ§λ€ λ 보면 μ΄λ κ² includes Tests κ° μλλ° μ΄κ±Έ 체ν¬νκ³ νλ‘μ νΈλ₯Ό μμ±νλ©΄ μΆκ°λ‘ Tests ν΄λκ° λ μκΈ΄λ€.

μμ±λ κ²
- (νλ‘μ νΈ λͺ
) + Tests
- (νλ‘μ νΈ λͺ ) + Tests
- (νλ‘μ νΈ λͺ
) + UITests
- (νλ‘μ νΈ λͺ ) + UITests
- (νλ‘μ νΈ λͺ ) + LaunchTests
μ€ν
- Build - cmd + B
- Test - cmd + U
Testλ₯Ό μμνλ©΄ μ±μ΄ 2κ°κ° μ€μΉλλ€.
μ²μμλ μΌλ°μ μΈ Tests μ½λλ€λΆν° μ§νλκ³ κ·Έλ€μμλ UITestsλ₯Ό μ§ννλλ° μ΄κ±΄ μκ°μ΄ μ€λ κ±Έλ¦°λ€.
κ·Έλ¦¬κ³ UITestsκ° μ’ λ£λλ©΄ λ€ν¬ λͺ¨λλ‘ λ³νλ€ γ γ ;;
π§ ν μ€νΈ μ½λ μμ± μλ Ή
First Test μμ± λ°©λ²
- ν μ€νΈ λ©μλμ μ΄λ¦μ νμ testλ‘ μμνκ³ κ·Έ λ€μ ν μ€νΈ λμμ λν μ€λͺ μ΄ μ¨λ€.
- given, when, then μΉμ
μΌλ‘ λλλ νμμ΄ μ’λ€.
- given: νμν κ°μ μ€μ νλ€. κ·Έλ¦¬κ³ μμ κ°μ΄λ λΉκ΅ν λ μ°μΈλ€.
- when : ν μ€νΈ μ€μΈ μ½λλ₯Ό μ€ννλ μΉμ μ΄λ€.
- then : ν μ€νΈκ° μ€ν¨νλ©΄ μΈμλλ λ©μμ§μ ν¨κ» μμν κ²°κ³Όλ₯Ό μ£Όμ₯νλ μΉμ μ΄λ€.
μμ
func testScoreIsComputedWhenGuessIsHigherThanTarget() {
// given
let guess = sut.targetValue + 5
// when
sut.check(guess: guess)
// then
XCTAssertEqual(sut.scoreRound, 95, "Score computed from guess is wrong")
}
ν μ€νΈ λλ²κΉ
μ±μ λͺ©μ μ λ²κ·Έκ° μμ λ κ·Έκ²μ μ°Ύλ λ°©λ²μ μμ보μ.
μ€λ¨μ νμκΈ°μμ ν μ€νΈ μ€ν¨ μ€λ¨μ μ μΆκ°νλ€.
μ΄λ κ² νλ©΄ ν μ€νΈ λ©μλκ° μ€ν¨λ₯Ό μ°Ύμμ λ ν μ€νΈ μ€νμ΄ μ€μ§λλ€.
κ·Έλ¬λ©΄ λλ²κ·Έ μ½μμ κ²μ¬νμ λ μ΄λ€ κ°μ΄ λ¬Έμ κ° μλμ§ νμΈν μ μλ€.

XCTestExpectationμ μ¬μ©νμ¬ λΉλκΈ° μμ ν μ€νΈ
λͺ¨λΈμ ν μ€νΈνκ³ ν μ€νΈ μ€ν¨λ₯Ό λλ²κ·Έ νλ λ°©λ²μ λ°°μ μΌλ―λ‘ μ΄μ λΉλκΈ° μ½λ ν μ€νΈλ‘ λμ΄κ° μ°¨λ‘μ΄λ€.
URLSessionλ©μλλ λΉλκΈ°μμ λλ€. μ¦μ λ°νλμ§λ§ λμ€κΉμ§ μ€νμ΄ μλ£λμ§ μλλ€.
λΉλκΈ°μ λ©μλλ₯Ό ν μ€νΈνλ €λ©΄ XCTestExpectationλ₯Ό μ¬μ©ν΄μ λΉλκΈ°μ μμ μ΄ μλ£λ λκΉμ§ ν μ€νΈλ₯Ό λκΈ°μμΌμΌ νλ€.
λΉλκΈ° ν μ€νΈλ μΌλ°μ μΌλ‘ λ리λ―λ‘ λ λΉ λ₯Έ λ¨μ ν μ€νΈμ λ³λλ‘ μ μ§ν΄μΌ νλ€.
XCodeTest Method
- expectation(description:)
- XCTestExpectationμ 리ν΄νλ€.
- μμλλ κ²°κ³Ό κ°μ descriptionμ λ£λλ€.
- promise.fulfill()
- λΉλκΈ° λ©μλ μλ£ νΈλ€λ¬μ μ±κ³΅ 쑰건 ν΄λ‘μ μμ μ΄κ²μ νΈμΆνμ¬ κΈ°λκ° μΆ©μ‘±λμμμ νλκ·Έλ‘ μ§μ νλ€.
- wait(for:timeout:)
- λͺ¨λ κΈ°λκ° μΆ©μ‘±λκ±°λ timeout λμ΄μ κ°κ²©μ΄ λλ λκΉμ§ ν μ€νΈλ₯Ό κ³μ μ€ννλ€.
Failing Fast
μ€ν¨λ μνμ§λ§ μμν 걸릴 νμλ μλ€.
URLμ νλ € μΌλΆλ‘ μ€ν¨νλ ν μ€νΈ μΌμ΄μ€λ₯Ό λ§λ€μ΄μ ν μ€νΈνλ€.
κ·Έλ λ€λ©΄ μ 체 μκ° μ΄κ³Όκ° λλ κ°κ²©μ΄ ꡬν΄μ§λ€. μλνλ©΄ νμ μ±κ³΅ν κ±°λΌκ³ κ°μ νκ³ , κ±°κΈ°μ promise.fulfill()μ λΆλ κΈ° λλ¬Έμ΄λ€.
requestκ° μ€ν¨λμκΈ° λλ¬Έμ μ€μ§ μ νμκ°μ΄ λ§λ£λμμ λλ§ μ’ λ£κ° λλ€.
κ°μ μ λ³κ²½νμ¬ μ΄λ₯Ό κ°μ νκ³ ν μ€νΈκ° λ 빨리 μ€ν¨νλλ‘ ν μ μλ€.
requestκ° μ±κ³΅ν λκΉμ§ κΈ°λ€λ¦¬λ λμ λΉλκΈ° λ©μλμ μλ£ μ²λ¦¬κΈ°κ° νΈμΆλ λκΉμ§ κΈ°λ€λ €λΌ..
μ΄λ μ±μ΄ μλ²λ‘λΆν° μλ΅(OK λλ μ€λ₯)μ μμ νλ μ¦μ λ°μνλ©°, μ΄λ μμμ μΆ©μ‘±νλ€.
κ·Έλ¬λ©΄ ν μ€νΈμμ μμ²μ΄ μ±κ³΅νλμ§ μ¬λΆλ₯Ό νμΈν μ μλ€.
Failing Conditionally
μ΄λ€ μν©μμλ ν μ€νΈλ₯Ό μ€ννλ κ²μ΄ μλ―Έκ° μλ€.
μλ₯Ό λ€μ΄, testValidApiCallGetsHTTPStatusCode200() λ€νΈμν¬ μ°κ²° μμ΄ μ€ννλ©΄ μ΄λ»κ² λ κΉ?
λ¬Όλ‘ 200 μν μ½λλ₯Ό λ°μ§ λͺ»νκΈ° λλ¬Έμ ν΅κ³Όν΄μλ μ λλ€.
κ·Έλ¬λ μ무κ²λ ν μ€νΈνμ§ μμκΈ° λλ¬Έμ μ€ν¨νμ§ μμμΌ νλ€.
XCTSkipUnless(_:_:)λ₯Ό μ¬μ©ν λ λ€νΈμν¬μ μ°κ²°ν μ μμΌλ©΄ ν μ€νΈλ₯Ό 건λλ΄λ€.
λ€νΈμν¬ μ°κ²°μ λΉνμ±ννκ³ ν μ€νΈλ₯Ό μ€ννμ¬ μ΄λ₯Ό νμΈν΄λΌ.
ν μ€νΈ μμ μλ μ¬λ°±μ ν μ€νΈκ° ν΅κ³Όνκ±°λ μ€ν¨νμ§ μμμμ λνλ΄λ μ μμ΄μ½μ΄ νμλλ€.
Faking Objects and Interactions
λΉλκΈ° ν μ€νΈλ μ½λκ° λΉλκΈ° APIμ λν μ¬λ°λ₯Έ μ λ ₯μ μμ±νλ€λ νμ μ μ€λ€.
URL μΈμ μμ μ λ ₯μ λ°μ λ μ½λκ° μ¬λ°λ₯΄κ² μλνλμ§, λλ UserDefaults λ°μ΄ν°λ² μ΄μ€ λλ iCloud 컨ν μ΄λλ₯Ό μ¬λ°λ₯΄κ² μ λ°μ΄νΈνλμ§ ν μ€νΈν μλ μλ€.
λλΆλΆμ μ±μ μ¬μ©μκ° μ μ΄ν μ μλ μμ€ν λλ λΌμ΄λΈλ¬λ¦¬ κ°μ²΄μ μνΈ μμ©νλ€. μ΄λ¬ν κ°μ²΄μ μνΈ μμ©νλ ν μ€νΈλ λλ¦¬κ³ λ°λ³΅ν μ μμΌλ©° 첫 λ²μ§Έ μμΉ μ€ λ κ°μ§λ₯Ό μλ°ν μ μλ€. λμ μ€ν μμ μ λ ₯μ λ°κ±°λ λͺ¨μ κ°μ²΄λ₯Ό μ λ°μ΄νΈνμ¬ μνΈ μμ©μ μμ‘°ν μ μλ€.
μ½λκ° μμ€ν λλ λΌμ΄λΈλ¬λ¦¬ κ°μ²΄μ μ’ μλμ΄ μλ κ²½μ° κ°μ§λ₯Ό μ¬μ©νλ€. κ·Έ λΆλΆμ μ°κΈ°ν κ°μ§ κ°μ²΄λ₯Ό λ§λ€κ³ μ΄ κ°μ§λ₯Ό λΉμ μ μ½λμ μ£Όμ ν¨μΌλ‘μ¨ μ΄κ²μ μνν΄λΌ. John Reidμ Dependency Injectionμ μ΄λ₯Ό μν λͺ κ°μ§ λ°©λ²μ μ€λͺ νλ€.
Faking Input From Stub
μ΄ ν μ€νΈλ λ κ°μ§ μμ μ μννλ€.
- κ°μ§ λ°μ΄ν°μ μλ΅μ μ€μ νκ³ κ°μ§ μΈμ κ°μ²΄λ₯Ό λ§λ λ€. λ§μ§λ§μΌλ‘ κ°μ§ μΈμ μ sutμ μμ±μΌλ‘ μ±μ μ£Όμ νλ€.
- μ€ν μ΄ λΉλκΈ° λ©μλλ‘ κ°μ₯νκΈ° λλ¬Έμ μ¬μ ν λΉλκΈ° ν μ€νΈλ‘ μμ±ν΄μΌ νλ€. startNewRound(completion:)λ₯Ό νΈμΆνλ©΄ targetValueμ stubed κ°μ§ λ²νΈλ₯Ό λΉκ΅νμ¬ κ°μ§ λ°μ΄ν°λ₯Ό ꡬ문 λΆμνλμ§ νμΈνλ€.
ν μ€νΈλ₯Ό μ€νν©λλ€. κ·Έκ²μ μ€μ λ€νΈμν¬ μ°κ²°μ΄ μκΈ° λλ¬Έμ κ½€ 빨리 μ±κ³΅ν κ²μ΄λ€!
Faking an Update to Mock Object
μ΄μ ν μ€νΈμμλ μ€ν μ μ¬μ©νμ¬ κ°μ§ κ°μ²΄λ‘λΆν°μ μ λ ₯μ μ 곡νλ€.
κ·Έλ° λ€μ Mock Objectλ₯Ό μ¬μ©νμ¬ μ½λκ° μ¬μ©μ κΈ°λ³Έκ°μ μ¬λ°λ₯΄κ² μ λ°μ΄νΈνλμ§ ν μ€νΈνλ€.
UI Testing in Xcode
UI ν μ€νΈλ₯Ό ν΅ν΄ μ¬μ©μ μΈν°νμ΄μ€μμ μνΈ μμ©μ ν μ€νΈν μ μλ€.
UI ν μ€νΈλ μΏΌλ¦¬λ‘ μ±μ UI κ°μ²΄λ₯Ό μ°Ύκ³ μ΄λ²€νΈλ₯Ό ν©μ±ν λ€μ ν΄λΉ κ°μ²΄μ μ΄λ²€νΈλ₯Ό 보λ΄λ λ°©μμΌλ‘ μλνλ€.
APIλ₯Ό μ¬μ©νλ©΄ UI κ°μ²΄μ μμ± λ° μνλ₯Ό κ²μ¬νμ¬ μμ μνμ λΉκ΅ν μ μλ€.
tap() μ΄λ κ² νλ©΄ λΆν λ 컨νΈλ‘€μ κ° λ²νΌμ μ¬λ°λ₯Έ λ μ΄λΈμ΄ μλμ§ νμΈνλ€. ν μ€νΈλ₯Ό μ€ννμμμ€. λͺ¨λ μ΄μ€μ μ΄ μ±κ³΅ν΄μΌ νλ€.
Testing Performance
Apple λ¬Έμ μμ :
μ±λ₯ ν μ€νΈλ νκ°νλ €λ μ½λ λΈλ‘μ μ¬μ©νμ¬ 10λ² μ€ννμ¬ μ€νμ λν νκ· μ€ν μκ°κ³Ό νμ€ νΈμ°¨λ₯Ό μμ§ν©λλ€. μ΄λ¬ν κ°λ³ μΈ‘μ κ°μ νκ· μ ν μ€νΈ μ€νμ λν κ°μ νμ±ν λ€μ κΈ°μ€μ κ³Ό λΉκ΅νμ¬ μ±κ³΅ λλ μ€ν¨λ₯Ό νκ°ν μ μμ΅λλ€.
μ±λ₯ ν μ€νΈλ₯Ό μμ±νλ κ²μ κ°λ¨νλ€.
μΈ‘μ νλ €λ μ½λλ₯Ό measure()μ ν΄λ‘μ μ λ°°μΉνκΈ°λ§ νλ©΄ λλ€.
λν μΈ‘μ ν μ¬λ¬ λ©νΈλ¦μ μ§μ ν μ μλ€.
- XCTClockMetric
- κ²½κ³Ό μκ°μ μΈ‘μ νλ€.
- XCTCPUMetric
- CPU μκ°, μ£ΌκΈ° λ° λͺ λ Ή μλ₯Ό ν¬ν¨ν CPU νλμ μΆμ νλ€.
- XCTStorageMetric
- ν μ€νΈν μ½λκ° μ€ν 리μ§μ μ°λ λ°μ΄ν°μ μμ μλ €μ€λ€.
- XCTMemoryMetric
- μ¬μ©λ 물리μ λ©λͺ¨λ¦¬μ μμ μΆμ νλ€.
ν μ€νΈλ₯Ό μ€νν λ€μ νν ν΄λ‘μ μ μμ λΆλΆ μμ λνλλ μμ΄μ½μ ν΄λ¦νμ¬ measure() ν΅κ³λ₯Ό νμΈνλ€.
μΈ‘μ νλͺ© μμ μλ μ νν μΈ‘μ νλͺ©μ λ³κ²½ν μ μλ€.
ππ» Ref
https://www.raywenderlich.com/21020457-ios-unit-testing-and-ui-testing-tutorial#toc-anchor-011
iOS Unit Testing and UI Testing Tutorial
Learn how to add unit tests and UI tests to your iOS apps, and how you can check on your code coverage.
www.raywenderlich.com
https://yagom.net/courses/unit-test-μμ±νκΈ°/
Unit Test μμ±νκΈ° - μΌκ³°λ·λ·
Unit Test μμ±νκΈ° ν μ€νΈλ₯Ό μμ±νλ©΄ μ’λ€λ λ§μ λ§μ΄ λ€μ΄λ³΄μ ¨μ κ² κ°μ΅λλ€. νμ§λ§ λ§μ ν μ€νΈλ₯Ό μμ±ν΄λ³΄λ €κ³ [β¦]
yagom.net