WWDC24) Swift testing์ผ๋ก ํ ์คํธ ์ฌํํ๊ธฐ
๐ Swift testing์ผ๋ก ํ ์คํธ ์ฌํํ๊ธฐ (Xcode 16 ๊ธฐ์ค)
- ํ ์คํธ๋ ๊ฐ๋ฐ ํ๋ก์ธ์ค์ ์ค์ํ ๋จ๊ณ
- ์ฝ๋๊ฐ ์ฌ์ฉ์์๊ฒ ์ ๋ฌ๋๊ธฐ ์ ์ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋ฐ์ด๋ ํ์ง์ ์ ํ์ ์ถ์ ํ ์ ์๋ค๋ ์์ ๊ฐ
- ๊ณ์ ๋์ด๋๋ ํ ์คํธ ๋ชจ์ ๊ด๋ฆฌ์ ์ด๋ ค์
- ์ฝ๋๊ฐ ๋ณต์กํด์ง์๋ก ํ ์คํธ๋ฅผ ์ฝ๊ณ ์ดํดํ๊ธฐ ์ฝ๋๋ก ๋ง๋๋๊ฒ ์ค์
- ์ฝ๋์์ ๋ฐ์ํ ์ ์๋ ๋ชจ๋ ์์ง ์ผ์ด์ค๋ฅผ ๋ค๋ฃจ๋ ค๋ฉด ๋ง์ ๋ ธ๋ ฅ ํ์
- ๋๊ท๋ชจ ํ ์คํธ ์ปฌ๋ ์ ์ ๊ตฌ์ฑํ๊ณ ์ฐ๊ด์ง๋ ๊ฒ์ ๋ณต์กํ ์ผ์ด ๋ ์ ์์
- ํ ์คํธ ์ฌ์ด์ ์จ๊ฒจ์ง ์ข ์์ฑ > ํ ์คํธ ์ทจ์ฝ, ์๊ธฐ์น ์์ ์ค๋ฅ
1๏ธโฃ Swift Testing ๊ฐ์
- Swift Testing์ Xcode 16์ ์๋กญ๊ฒ ๋์ ๋ ๊ณต์ ์คํ์์ค ํ ์คํธ ํ๋ ์์ํฌ.
- ๊ธฐ์กด XCTest์ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ณ , ํํ๋ ฅ ์๊ณ ์ ์ง๋ณด์๊ฐ ์ฌ์ด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ์ง์. (Expressive code)
- Swift ์ธ์ด ์์ฒด์ ํน์ฑ๊ณผ ๋ฌธ๋ฒ์ ์ ๊ทน์ ์ผ๋ก ํ์ฉํจ.
2๏ธโฃ ๊ธฐ๋์น(Expectation) ์์คํ : ์ฝ๋๊ฐ ์์๋๋ก ์๋ํ๋์ง
โ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋์น
- expect(value == true) ๋๋ expect(user.name).toEqual("Suvera") ๋ฑ์ผ๋ก ์ฝ๋์ ์๋๋ฅผ ๋ช ํํ ํํ.
- expect() ๋ด๋ถ๋ ์ผ๋ฐ Bool์ด ์๋๋ผ matcher ๊ธฐ๋ฐ DSL๋ก ๋์ํจ.
โ ์ค๋ฅ ์ฒ๋ฆฌ ๊ธฐ๋์น – expect throws
- ์ฝ๋์ ํดํผ ํจ์ค๋ฅผ ํ ์คํธํ๊ณ throw ํจ์๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๋ฐํ๋๊ธฐ๋ฅผ ๊ธฐ๋ -> ํ ์คํธ ๋ด๋ถ์์ ํธ์ถ
- ํจ์๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์คํ๋๊ณ ๊ฐ์ ๋ฐํํ๋ฉด ๊ธฐ๋์น๋ฅผ ์ฌ์ฉํ์ฌ ์์๊ณผ ๋ง๋์ง ํ์ธ ๊ฐ๋ฅ
- ๋ฐ๋ฉด, ์คํจ ์ฌ๋ก๊ฐ ์๋๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด ํจ์๊ฐ ๋ฐ์์ํจ ์ค๋ฅ๋ฅผ catchํ๊ณ ๊ฒ์ฌํด์ผ ํจ.
- ์ค๋ฅ๋ฅผ throwํ ๊ฒ์ผ๋ก ๊ธฐ๋๋๋ ์ฝ๋์ ๋ํ ํ ์คํธ๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์์ฑ.
import Testing
@Test func brewTeaError() throws {
let teaLeaves = TeaLeaves(name: "EarlGrey", optimalBrewTime: 4)
#expect(throws: (any Error).self) {
try teaLeaves.brew(forMinutes: 200) // We don't want this to fail the test!
}
}
- ํน์ ์ค๋ฅ ํ์ ๊ฒ์ฆ : ๋ชจ๋ ์๋ฌ๋์ ํด๋น ํ์ ์ ๋ฌ
import Testing
@Test func brewTeaError() throws {
let teaLeaves = TeaLeaves(name: "EarlGrey", optimalBrewTime: 4)
#expect(throws: BrewingError.self) {
try teaLeaves.brew(forMinutes: 200) // We don't want this to fail the test!
}
}
- ์ปค์คํ ๊ฒ์ฆ๋ ๊ฐ๋ฅ: ์ค๋ฅ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๋ง์ถคํํด ํน์ ํ์ ์ด๋ ์ค๋ฅ ์ฌ๋ก ์ฐ๊ฒฐ๋ ๊ฐ ๋๋ ์์ฑ์ด ์ฌ๋ฐ๋ฅธ์ง ์ฌ๋ถ
- ๋๋ ์ฝ๋์์ ๋ฐ์ํ ์ค๋ฅ๊ฐ ์์ ์ ๋ง๋ ์ค๋ฅ์ธ์ง ํ์ธํ๋ ๋ฑ
import Testing
@Test func brewTeaError() throws {
let teaLeaves = TeaLeaves(name: "EarlGrey", optimalBrewTime: 4)
#expect(throws: BrewingError.oversteeped) {
try teaLeaves.brew(forMinutes: 200) // We don't want this to fail the test!
}
}
import Testing
@Test func brewTea() {
let teaLeaves = TeaLeaves(name: "EarlGrey", optimalBrewTime: 4)
#expect {
try teaLeaves.brew(forMinutes: 3)
} throws: { error in
guard let error = error as? BrewingError,
case let .needsMoreTime(optimalBrewTime) = error else {
return false
}
return optimalBrewTime == 4
}
}
3๏ธโฃ ํ์ ๊ธฐ๋์น – require
- ์ต์ ๋ ๊ฐ์ด nil์ด๋ฉด ์กฐ๊ธฐ์ ํ ์คํธ๋ฅผ ์ข ๋ฃ์ํด.
- ์: guard let ๊ฐ์ ๋ ผ๋ฆฌ๋ฅผ require๋ก ํ ์คํธ์ ์ ์ฉ ๊ฐ๋ฅ.
import Testing
@Test func brewAllGreenTeas() {
#expect(throws: BrewingError.self) {
brewMultipleTeas(teaLeaves: ["Sencha", "EarlGrey", "Jasmine"], time: 2)
}
}
-> ๋ฐ์ํ๋ ๊ธฐ๋๊ฐ์ ํฌํจํ ๋ชจ๋ ์ผ๋ฐ ๊ธฐ๋๊ฐ์ ํ์ ๊ธฐ๋๊ฐ์ผ๋ก ๋ง๋ค ์ ์๋ค.
import Testing
@Test func brewAllGreenTeas() throws {
try #require(throws: BrewingError.self) {
brewMultipleTeas(teaLeaves: ["Sencha", "EarlGrey", "Jasmine"], time: 2)
}
}
- ์ต์ ๋ ๊ฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ๊ฒฝ์ฐ
-> ํ์ ๊ธฐ๋๊ฐ์ ์ฌ์ฉํ์ฌ ์ ์ด ํ๋ฆ์ ๋ฌธ์ํ ํ ์ ์๋ค.
-> ๋ง์ง๋ง์ nil์ด ๋ ๊ฐ์ ๊ฒ์ฌํ๋ ๊ฒ์ ์๋ฏธ๊ฐ ์์ผ๋ฏ๋ก ํ์ ๊ธฐ๋๊ฐ์ ์ถ๊ฐํ๋ฉด ํ ์คํธ๊ฐ ๋ ์ด์ ํ ์ผ์ด ์๋ ๊ฒฝ์ฐ ์กฐ๊ธฐ์ ์ข ๋ฃ
4๏ธโฃ ์คํจ๋ฅผ ํ์ฉํ๋ ํ ์คํธ – withKnownIssue
- ํ ์คํธ์์ ์๋ ค์ง ์ค๋ฅ๋ฅผ ๋ฌธ์ํํ๊ธฐ ์ํด ์ฌ์ฉ.
- ํ ์คํธ ์คํจ ๋ถ๋ฅ๋ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆผ > ์ฆ์ ์์ ๋ถ๊ฐ, ํต์ ํ ์ ์๋ ์์ธ.. ๋ ธ์ด์ฆ ์ถ๊ฐ๋์ด ์ค์ ๋ฌธ์ ๋ฅผ ์์์ฐจ๋ฆฌ์ง ๋ชปํจ.
- ์ธ๋ถ ์์ธ์ผ๋ก ์ธํด ์ผ์์ ์ผ๋ก ์คํจํ ์ ์๋ ํ ์คํธ๋ฅผ ์์๋ ์คํจ๋ก ์ฒ๋ฆฌ.
- ์ด ์ค๋ฅ๋ ํ ์คํธ ๋ณด๊ณ ์์์ ‘์์๋ ์คํจ(expected failure)’๋ก ๊ธฐ๋ก๋จ → ์ค์ ๋ฒ๊ทธ์ ๊ตฌ๋ถ ๊ฐ๋ฅ.
- ์ด ๊ธฐ๋ฅ์ CI/CD์์ ์ ๋ขฐํ ์ ์๋ ํผ๋๋ฐฑ ๋ฃจํ๋ฅผ ์ ์งํ ๋ ๋งค์ฐ ์ ์ฉ.
-> ํจ์๊ฐ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ฉด ์์ํ๋ ์ค๋ฅ์ด๊ธฐ ๋๋ฌธ์ ํ ์คํธ ๊ฒฐ๊ณผ๊ฐ ํ ์คํธ ์คํจ์ ํฌํจ๋์ง ์์ !!
-> ๋์ ๊ฒฐ๊ณผ์์ ์์ํ๋ ์คํจ๋ก ํ์๋จ.
-> ๋ฌธ์ ํด๊ฒฐ ๋์ด ๋ ์ด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฉด > ์๋ฆผ
- ํ ์คํธ์์ ์ฌ๋ฌ ํ์ธ ์ํ
- Custom test descriptions : ํ ์คํธ ๋ด๋ถ์์ ์ผ์ด๋๋ ์ผ์ ํ๋์ ํ์ , ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋ดํ ์ ์๋ค.
5๏ธโฃ ๋งค๊ฐ๋ณ์ํ๋ ํ ์คํธ – Parameterized Tests
- ์์ง ์ผ์ด์ค๋ฅผ ํฌ์ฐฉํ๊ธฐ ์ํด ๋ค์ํ ์กฐ๊ฑด์์ ํ ์คํธ ์คํํ๋ ๊ฑด ์ข์ง๋ง ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆผ
- ๊ฐ๋ฅํ ๋ชจ๋ ๋ณ์์ ๋ํด ๋ณ๋์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ ์ง๊ด๋ฆฌ ํ๋ฌ > swift testing > ๋ค์ํ ์ธ์๋ก ๋จ์ผ ํ ์คํธ ํจ์ ์ฝ๊ฒ ์คํ
โ ๋ชฉ์
- ๋ฐ๋ณต์ ์ธ ํ ์คํธ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๊ณ , ํ๋์ ํ ์คํธ ํจ์๋ก ๋ค์ํ ์ ๋ ฅ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ํจ.
- ํ ์คํธ ์ผ์ด์ค๋ ์๋ก ์์ ํ ๋ ๋ฆฝ์ , ๋ณ๋ ฌ๋ก ์คํ ๊ฐ๋ฅ
- ๋ชจ๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ํ ์คํธํ๋๋ฐ ํ์ํ ์๊ฐ์ด for๋ฃจํ๋ ๋ณ๋์ ํ ์คํธ ํจ์๋ฅผ ์ฌ์ฉํ ๋๋ณด๋ค ์ค์ด๋ญ๋๋ค.
- xcode๋ ์ ๋ ฅ ์ ํ์ด Codable์ ์ฑํํ๋ ๊ฒฝ์ฐ ํ ์คํธ ํจ์์ ๊ฐ๋ณ ํ ์คํธ ์ผ์ด์ค ์ฌ์คํ์ ์ง์.
- ์ด๋ฅผ ํตํด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋ ๋ค๋ฅธ ํ ์คํธ ์ผ์ด์ค๋ฅผ ๋ค์ ์คํํ ํ์์์ด ์คํจํ ํ ์คํธ ์ผ์ด์ค๋ง์ ์ฌ์๋
โ ๋จ์ผ ์ธ์ ์์
- ๊ฐ ์ธ์๋ ํ ์คํธ ๋ด๋น๊ฒ์ดํฐ์์ ๋ณ๋์ ์คํ ๋จ์๋ก ๋ถ๋ฆฌ, ๋ณ๋ ฌ ์คํ ๊ฐ๋ฅ.
โ ๋ค์ค ์ธ์ ์์
- zip์ ํ์ฉํด ๋ชจ๋ ์กฐํฉ์ด ์๋๋ผ 1:1 ๋งคํ๋ง ํ ์คํธํ ์ ์์.
=> ์ด๋ฌํ ์ฆ๊ฐ๋ฅผ ์ ์ดํ๊ธฐ ์ํด ํ ์คํธํจ์๋ ์ต๋ ๋๊ฐ์ ์ปฌ๋ ์ ์ ํ์ฉ
=> Swift ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ zip ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํจ๊ป ์ฌ์ฉํด์ผํ๋ ์ ๋ ฅ ์์ ์ง์ง์ ์๋ ์๋ค
- zip์ ํํ์ ์ํ์ค๋ฅผ ์์ฑ
6๏ธโฃ ํ ์คํธ ์ ๋ฆฌ ์ ๋ต: ๋ชจ์๊ณผ ํ๊ทธ
โ ํ ์คํธ ๋ชจ์(Collection)
- ํ ์คํธ๋ฅผ ๋ ผ๋ฆฌ์ ๊ทธ๋ฃน์ผ๋ก ๊ตฌ์กฐํํ ์ ์๊ฒ ํจ.
- ํ์ ๋ชจ์์ ํฌํจํด ํธ๋ฆฌ ๊ตฌ์กฐ ํ์ฑ ๊ฐ๋ฅ.
- ๋ฐ๋ฏํ ๋์ ํธ, ์ฐฌ ๋์ ํธ
- add sub suites -> ํ ์คํธ ๊ทธ๋ฃน ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ ๋ช ํํ๊ฒ ๋ง๋ค ์ ์๋ค.
โ ํ๊ทธ(Tag)
- ํ์ผ/๋ชจ์์ ๊ด๊ณ์์ด ํ ์คํธ ๊ฐ ๋ ผ๋ฆฌ์ ์ฐ๊ฒฐ์ ์ํ ๋๊ตฌ.
- ์: caffeinated, chocolatey, spicy, experimental
- ํ๊ทธ ๊ธฐ๋ฐ์ผ๋ก ํ ์คํธ ์คํ, ํํฐ๋ง, ๊ทธ๋ฃนํ, ํ ์คํธ ๊ณํ ๊ตฌ์ฑ ๊ฐ๋ฅ
- ๋ณต์กํ ํจํค์ง๋ ํ๋ก์ ํธ์๋ ์๋ฐฑ ~ ์์ฒ๊ฐ์ ํ ์คํธ์ ๋ชจ์์ด ํฌํจ ๋ ์ ์์
- ์ผ๋ถ ํ ์คํธ์ ํ์ ์ธํธ๋ ๊ณตํต๋ ํน์ฑ์ ๊ณต์ ํ ์ ์์
- ์ ์ํ ์ : ํ๊ทธ๋ ํ ์คํธ ๋ชจ์์ ๋์ฒดํ ์ ์๋ค.
- ๋ชจ์์ ์์ค ์์ค์์ ํ ์คํธ ํจ์์ ๊ตฌ์กฐ๋ฅผ ๋ถ์ฌํ์ง๋ง ํ๊ทธ๋ ๊ณตํต์ ์ ๊ณต์ ํ๋ ์๋ก ๋ค๋ฅธ ํ์ผ, ๋ชจ์, ๋์์ ํ ์คํธ๋ฅผ ์ฐ๊ฒฐํ ์ ์๋๋ก ํจ.
ํ๊ทธ ์ ์ธ ๋ฐฉ๋ฒ
- ๋ชจ๋ ์๋ฃ์ ์นดํ์ธ์ด ๋ค์ด์๊ณ , ์์คํ๋ ์ ๋ธ๋ผ์ฐ๋๋ ๋ง์ฐฌ๊ฐ์ง
-> caffeinated ํ๊ทธ๋ฅผ ๋ง๋ค์ด ํ ์คํธ๊ฐ ๋ณ๋์ ๋ชจ์์ ์กด์ฌํด๋ ์๋ก ์ฐ๊ด์ํฌ ์ ์์
- ๋น๋ฐ ์ฌ๋ฃ -> tag ์์ฑ์ ๋ณ์์ ์ถ๊ฐํด ํ ์คํธ์์ ํ๊ทธ๋ก ์ฌ์ฉํ ์ ์๋๋ก
- ํ๊ทธ๊ฐ ์ฌ๋ฌ๊ฐ ์์ ์ ์๋ค.
- ๋ชจ์นด์ ์์คํ๋ ์ ๋ธ๋ผ์ฐ๋๋ ๋ชจ๋ ์นดํ์ธ์ด ์์ง๋ง ์ฌ๋ฃ๊ฐ ์ด์ฝ๋ฆฟ์
-> ํ ์คํธ ๋ด๋น๊ฒ์ดํฐ๊ฐ ํ ์คํธ๋ฅผ ํ๊ทธ๋ณ๋ก ๊ทธ๋ฃนํํ์ฌ ํน์ ํ๊ทธ๊ฐ ์๋ ํ ์คํธ๋ฅผ ์คํํ ์ ์๊ฒ ํจ
- ๋ด๋น๊ฒ์ดํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ค ์ฝ๋์์ ํด๋น ์์น์ ๋ฐ๋ผ ์ ๋ฆฌ๋ ํ ์คํธ๋ฅผ ํ์
- ํ ์คํธ ๋ด๋น๊ฒ์ดํฐ ํ๋จ์ ํํฐ ํ๋๋ฅผ ์ฌ์ฉํด ํซ์์ค ๊ด๋ จ ํ ์คํธ ์ฐพ๊ธฐ
- xcode์ ํ๊ทธ ์ ์
- seasonal, spicy, street food์ ๊ฐ์ ํ๊ทธ ์ ์ ํ์
- ๊ธฐ๋ณธ์ ์ผ๋ก ํํฐ ํ๋๋ ํ ์คํธ์ ํ์, ํจ์ ์ด๋ฆ๊ณผ ์ผ์น
- ์ง์ ๋ธ๋ ๋ ์ฟ ํค์ ์คํ์ด์ค ์กฐํฉ๊ณผ ์๊ธ์น์ ์ํฐ์ดํฌ ๋ฅ์์ค ๋น์จ ๋ฑ์ ํ ์คํธ๊ฐ ํ์
- ์ด๋ฆ์ ๊ฐ์กฐ ํ์๋ ๋จ์ด๊ฐ ์๋ ํ ์คํธ๋ฅผ ์ ์ -> ์ผ์นํ๋ ํ๊ทธ๊ฐ ์๊ธฐ ๋๋ฌธ
- ์ ์ ํ์ ์์ spicy ํด๋ฆญ > ์ ๋ ฅํ ๋ด์ฉ์ ํ ์คํธ ๋ด๋น๊ฒ์ดํฐ๊ฐ ํ๊ทธ ํํฐ๋ก ๋ณํ > ํด๋น ํ๊ทธ๊ฐ ์๋ ๋ชจ๋ ํ ์คํธ๋ฅผ ์ ๊ฑฐ
7๏ธโฃ ํ ์คํธ ๊ณํ(Test Plan)
- ์ ๋ขฐํ ์ ์๋ ํต์ฌ ํ ์คํธ ์ธํธ๊ฐ ์๋ ํ ์คํธ ๊ณํ ๋ง๋ค๊ธฐ ๊ฐ๋ฅ
- ๋ณ๊ฒฝ ์ ๋ฐ์ํ ์ ์๋ ๋ฒ๊ทธ๋ฅผ ๋น ๋ฅด๊ฒ ํฌ์ฐฉ
- Include Tags, Exclude Tags ๊ธฐ๋ฅ ์ ๊ณต.
- ์: @seasonal, @unreleased ํ๊ทธ๋ฅผ ์ ์ธํ ํต์ฌ ํ ์คํธ๋ง ์คํ.
- Xcode ๋ด์์ ํ๊ทธ๋ณ ์คํ ๋ฐ ๋ณด๊ณ ์ ๋ถ์ ๊ฐ๋ฅ.
- UI์์ ํ๊ทธ ๊ธฐ๋ฐ ํ ์คํธ ์คํ → ํน์ ๊ธฐ๋ฅ์ด๋ ์๊ธฐ๋ณ ํ ์คํธ ๊ตฌ์ฑ ๊ฐ๋ฅ.
- ํ ์คํธ ๊ณํ ์ ๋ฐ์ดํธ : ๋ชจ๋ ํต์ฌ ํ ์คํธ ์คํ, sesonal ํ๊ทธ๊ฐ ์๋ ํ ์คํธ ์ ์ธ
- ํ ์คํธ ๋ณด๊ณ ์
- spicy ํ๊ทธ ๊ด๋ จ ๋ชจ๋ ํ ์คํธ๊ฐ ์คํจ
8๏ธโฃ ๋ณ๋ ฌ ์คํ & ์ง๋ ฌํ ์ ์ด
โ ๋ณ๋ ฌ ํ ์คํธ
- Swift Testing์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๋ ฌ ์คํ์ ์ง์.
- ๋ชจ๋ ๋ฌผ๋ฆฌ์ ๊ธฐ๊ธฐ์์ ๋ณ๋ ฌ ํ ์คํธ ์คํ ํ ์ ์์
- ๋๊ธฐ/๋น๋๊ธฐ ์ฌ๋ถ ๊ด๊ณ์์ด ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌ๋จ.
- ํ ์คํธ ์คํ ์์๋ฅผ ๋๋คํ(shuffled) ํ์ฌ ํ ์คํธ ๊ฐ ์จ๊ฒจ์ง ์์กด์ฑ ๊ฐ์ง ๊ฐ๋ฅ.
- XCTest์ ํฐ ์ฐจ์ด์ : ์ฌ๋ฌ ํ๋ก์ธ์ค๋ฅผ ์ฌ์ฉํ๋ ๋ณ๋ ฌํ๋ง ์ง์ํ์ฌ, ํ๋ฒ์ ํ๋์ ํ ์คํธ๋ง ์คํํ๋ ๊ฒ๊ณผ๋ ๋ค๋ฆ
- ํ ์คํธ ํจ์๋ฅผ MainActor๊ฐ์ ๊ธ๋ก๋ฒ ์กํฐ์ ๊ฒฉ๋ฆฌ ๊ฐ๋ฅ
- ์ด์ ํ ์คํธ ์ฝ๋๋ฅผ ๋ณํํ๋ ๊ฒฝ์ฐ, ์ด๋ฌํ ์ข ์์ฑ ์ค ์ผ๋ถ๊ฐ ์ด๋ฏธ ๋ฒ ์ดํฌ ๋์ด ์์ ์ ์๋ค.
- ์ค์ํํธ 6์ ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ค์ ์์ฑํ ๋ ์ผ๋ถ ๋ฌธ์ ๋ฐ๊ฒฌ์ ๋์์ด ๋ ์ ์์ง๋ง ๋ค๋ฅธ ๋ฌธ์ ๋ ์ฐพ๊ธฐ ํ๋ฌ
- ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ก ์ฝ๋๋ฅผ swift testing์ผ๋ก ๋ณํํ๊ณ ๋ฌธ์ ๋ ๋์ค์ ํด๊ฒฐํ๊ณ ์ถ์์๋
โ ์ง๋ ฌ ์คํ ์ ์ด
- @serialized ๋ชจ์ ๋๋ ํ ์คํธ ํจ์์ ์ ์ฉ → ํ ์คํธ๋ฅผ ์์๋๋ก ์คํ.
- ํ์ ๋ชจ์์๋ ์ ์ฉ๋จ (์๋ ์์๋จ).
-> ๊ฐ๋ฅํ๋ค๋ฉด ๋จผ์ ํ ์คํธ ์ฝ๋๋ฅผ ๋ณ๋ ฌ๋ก ์คํํ๋๋ก ๋ฆฌํฉํ ๋ง ํ๋ ๊ฒ์ ๊ณ ๋ ค !
- .serialized๋ ๋งค๊ฐ๋ณ์ํ๋ ํ ์คํธ ํจ์์ ์ ์ฉ๋์ด ํ ์คํธ ์ผ์ด์ค๊ฐ ํ๋ฒ์ ํ๋์ฉ ์คํ๋๋๋ก ํ ์๋ ์์
- ๊ทธ๋ฌ๋ ์ค์ํํธ๋ ์ด๋ฐ ์ง๋ ฌํ๋ ํ ์คํธ์ ๊ด๋ จ ์๋ ๋ค๋ฅธ ํ ์คํธ๋ ๋ณ๋ ฌ์ผ๋ก ์คํ ๊ฐ๋ฅ
- ๋ณ๋ ฌ ํ ์คํธ ๊ธฐ๋ณธ : ๋น ๋ฅด๊ฒ ์คํ
- ๋ณ๋ ฌ๋ก ๋ฆฌํฉํ ๋ง ๊ณ ๋ ค
9๏ธโฃ ๋น๋๊ธฐ ํ ์คํธ์ ์ฝ๋ฐฑ
โ async/await ์ง์
- Swift์ async/await ๊ทธ๋๋ก ์ฌ์ฉ ๊ฐ๋ฅ.
- Swift Testing์ Task ๋ด๋ถ์์๋ ์์ฐ์ค๋ฝ๊ฒ ์๋ํจ.
- ์์ ์ด ์ข ๋ฃ๋๋ ๋์ ๋ค๋ฅธ ํ ์คํธ ์ฝ๋๊ฐ cpu๋ฅผ ๊ณ์ ์ฌ์ฉํ ์ ์๊ฒ ํ ์คํธ๋ฅผ ์ผ์ ์ค๋จ
โ ์๋ฃ ํธ๋ค๋ฌ → continuation ๋ณํ
- completionHandler ๊ธฐ๋ฐ ์ฝ๋๋ async๋ก ์ฝ๊ฒ ๋ํ ๊ฐ๋ฅ.
- c, obj-c: ์๋ฃ ํธ๋ค๋ฌ๋ก ๋น๋๊ธฐ ์์ ์ ๋์ ์๋ฆผ
โ ์ด๋ฒคํธ ํ์ธ – confirmation
- ์ด๋ฒคํธ๊ฐ ๋ช ๋ฒ ํธ์ถ๋๋์ง ํ์ธ ๊ฐ๋ฅ (confirmation(count:))
- ๊ธฐ๋ณธ๊ฐ์ 1ํ, 0 ์ค์ ์ ํธ์ถ๋์ง ์์์ผ ํ๋ ์ํฉ ๊ฒ์ฆ ๊ฐ๋ฅ.
๋ ๋ค๋ฅธ ์ฝ๋ฐฑ์ ๋๋ฒ ์ด์ ์คํ ๋ ์ ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ
- ์ ์ฒด ์์๊ฐ ใท๋๋ ๋๋ง๋ค ์ฝ๋ฐฑ ํธ์ถ์ด ์๋๋ผ ๊ฐ ์ฟ ํค๋ง๋ค ํ๋ฒ ์ฉ ํธ์ถ
- ๋ณ์๋ฅผ ์ฌ์ฉํด ๋จน์ ์ฟ ํค์ ์๋ฅผ ๊ณ์ฐํ๋ ค๊ณ ํ๋ฉด ์ค์ํํธ 6์ ๋์ ์คํ ์ค๋ฅ๊ฐ ๋ฐ์
- ์ด๋ ๊ฒ ๋ณ์๋ฅผ ์ค์ ํ๋๊ฒ ์์ ํ์ง ์๊ธฐ ๋๋ฌธ์
- ํ ์คํธ ์ค์ธ ์ฝ๋๊ฐ ์ฝ๋ฐฑ์ ๋ ๋ฒ ์ด์ ํธ์ถํ ์ ์๊ณ , ํธ์ถ ํ์๋ฅผ ํ ์คํธํด์ผํ๋ ๊ฒฝ์ฐ confirmation ์ฌ์ฉ.
- ๋ค๋ฅธ ์์ ํ์๋ฅผ ์ง์ ํ ์๋ ์๋ค.
๐ ํ ์คํธ ์ธ์ฌ์ดํธ ๋ฐ ํ๊ทธ ๊ธฐ๋ฐ ๋ถ์
- ํ ์คํธ ๋ฆฌํฌํธ์ ํ๊ทธ ์ ๋ณด๊ฐ ํจ๊ป ํ์๋จ.
- ์คํจ ํจํด → ๊ณตํต ํ๊ทธ ๊ธฐ๋ฐ ๋ถ์ ๊ฐ๋ฅ (spicy ํ๊ทธ ํ ์คํธ๊ฐ ์ ๋ถ ์คํจํจ ๋ฑ).
- UI์์์ ํ๊ทธ๋ณ ์คํ ๋ฒํผ ๋ฐ ์คํจ ํํฐ ์ ๊ณต → ๋น ๋ฅธ ๋๋ฒ๊น ๊ฐ๋ฅ.
๐ง Swift Testing์ ์ฅ์ ์์ฝ
XCTest | Swift Testing | |
ํํ๋ ฅ | ์ ํ์ | ํ๋ถํ DSL ๊ธฐ๋ฐ |
์ค๋ฅ ํ ์คํธ | ๋ณต์กํจ (do-catch) | expect throws ํ ์ค ์ฒ๋ฆฌ |
๋งค๊ฐ๋ณ์ ํ ์คํธ | ์์ | @Test(arguments:) ์ง์ |
ํ๊ทธ/๋ฉํ๋ฐ์ดํฐ | ๋ถ๊ฐ๋ฅ | ํ๊ทธ ๋ฐ ์ ๋ฆฌ ๊ฐ๋ฅ |
๋ณ๋ ฌ ์คํ | ์ ํ์ | ๊ธฐ๋ณธ ๋ณ๋ ฌ, ์ง๋ ฌํ ์ ์ด ๊ฐ๋ฅ |
๋น๋๊ธฐ ์ง์ | ์ง์ | await ๋ฐ continuation ์์ ํตํฉ |
์ ์ง๋ณด์ | ๋ถํธํจ | ๊ตฌ์กฐํ๋ ๊ด๋ฆฌ ์ ๋ต |
๐ ๊ฒฐ๋ก
Swift Testing์ ํ
์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ ์ด์์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
ํ
์คํธ๋ฅผ ๊ตฌ์กฐํํ๊ณ ๋ณ๋ ฌํํ๋ฉฐ, ํ๊ทธ์ ๊ธฐ๋์น๋ฅผ ํตํด ์ ๊ตํ ์ปค๋ฒ๋ฆฌ์ง์ ํ์ง ๊ด๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ค๋๋ค.
XCTest๋ฅผ ๋์ด, Swift๋ค์ด ํ
์คํธ๋ฅผ ์ํ ์ ํ์ ์
๋๋ค.