๐ 2019.11.19 (ํ)
WWDC 2017 | Session : 414 | Category : Testing
๐
Engineering for Testability - WWDC 2017 - Videos - Apple Developer
- Prepare input
- Run the code being tested
- Verify output
- Control over inputs
- Visibility into outputs
- No hidden stage
- Protocols and parameterization
- Seperarting logic and effects
@IBAction func openTapped(_ sender: Any) {
let mode: String
switch segmentedControl.selectedSegmentIndex {
case 0: mode = "view"
case 1: mode = "edit"
default: fatalError("Impossible case")
}
let url = URL(string: "myappscheme://open?id=\(document.identifier)&mode=\(mode)")!
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
handleURLError()
}
}
์ฑ์ ๋ฐ์นญํด์ screen์ผ๋ก ์ด๋ํด์, ํญ ๋ฉ๋ด๋ฅผ ๋๋ฅด๊ณ , Open ๋ฒํผ์ ๋๋ฌ์ ๋ค๋ฅธ ์ฑ์ผ๋ก ๋ณ๊ฒฝ ๋์๋์ง ํ์ธ
โ run ํ๋๋ฐ ์ค๋ ๊ฑธ๋ฆฐ๋ค. ํนํ ๋ช๊ฐ์ ๋ค๋ฅธ doument ๊น์ง ํ์ธ ํ๋ ค๋ฉด. ๋ ํฐ ๋ฌธ์ ๋, UI Test๋ ์ฑ์ ๋ฐ๊พธ๊ธฐ ์ํ URL์ ๊ฒ์ฌ ํ ์ ์๋ค
์ฌ๊ธฐ์๋ URL์ ํ ์คํธ ํ๊ณ ์ถ์ ๊ฑฐ๊ธฐ ๋๋ฌธ์ Unit Test๊ฐ ์ ์ ํ๋ค.
func testOpensDocumentURLWhenButtonIsTapped() {
let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Preview") as! PreviewViewControllercontroller
controller.loadViewIfNeeded()
controller.segmentedControl.selectedSegmentIndex = 1
controller.document = Document(identifier: โTheID")
controller.openTapped(controller.button)
}
์์ ์ฝ๋ ์ค if UIApplication.shared.canOpenURL(url)
์ result ๊ฐ์, ๋ฉ์๋์ ๋ค๋ฅธ ์ธํ์ ์ํฅ์ ์ค๋ค
ํ์ง๋ง ์ด๊ฒ์ global system state์ ์์กด ํ๊ธฐ ๋๋ฌธ์, result์ query๋ฅผ ํ๋ก๊ทธ๋จ์ ์ผ๋ก ํ ์คํธ ํ ๋ฐฉ๋ฒ์ด ์๋ค
class DocumentOpener {
enum OpenMode: String {
case view
case edit
}
func open(_ document: Document, mode: OpenMode) {
let modeString = mode.rawValuelet url = URL(string: "myappscheme://open?id=\(document.identifier)&mode=\(modeString)")!
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
handleURLError()
}
}
}
-
ViewController๋ก ๋ถํฐ ๋นผ๊ณ ์์ํด๋ณด์
-
๋ก์ง๊ณผ ํ๋์ encapsulate ํ๊ธฐ ์ํ Document opener class์ด๋ค
-
ํ์ง๋ง ์ฌ์ ํ
UIApplication.shared.canOpenURL(url)
์ ๊ณ ์น ํ์๊ฐ ์๋ค.class DocumentOpener { let application: UIApplicationinit(application: UIApplication) { self.application = application }
func open(_ document: Document, mode: OpenMode) {
let modeString = mode.rawValue
let url = URL(string: "myappscheme://open?id=\(document.dientifier)&mode=\(modeString")!
if application.canOpenURL(url) {
application.open(url, options: [:], completionGandler: nil)
} else {
handleURLError()
}
}
}
class MockURLOpener: URLOpening {
var canOpen = false
var openedURL: URL?
func canOpenURL(_ url: URL) -> Bool {
return canOpen
}
func open(_ url: URL,options: [String: Any],completionHandler: ((Bool) -> Void)?) {
openedURL = url
}
}
Unit tests great for testing small, hard-to-reach code paths
UI tests are better at testing integration of larger pieces
Abstracting UI element queries
- Store parts of queries in a variable
- Wrap complex queries in utility methods
- Reduces noise and clutter in UI test
Creating objects and utility functions
Utilizing keyboard shortcuts