// MARK: Application Lifecycle
func application(
application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?)
-> Bool {
#if !TESTING
registerUINotificationStyles()
exportApplicationMetadataToNSUserDefaults()
loadStoryboard()
IRConnectivityManager.sharedInstance.setup()
#endif
return true
}
func isTesting() -> Bool {
// get launch arguments from NSProcessInfo
return NSProcessInfo.processInfo().arguments.contains("isTesting")
}
func isTesting() -> Bool {
// get launch arguments from NSProcessInfo
return NSProcessInfo.processInfo().environment["XCInjectBundle"] != nil
}
func isTesting() -> Bool {
return NSClassFromString("XCTestCase") != nil
}
expect(actual).to(equal(expected))
expect(actual).toNot(equal(expected))
expect(actual).to(beLessThan(expected))
expect(button).to(beAnInstanceOf(UIButton))
expect(string).to(beAKindOf(String))
expect(flag).to(beTrue())
expect(myArray).to(contain('koko'))
expect(myURL).to(contain("http://"))
expect(myURL).to(endWith(".io"))
expect(myArray).to(haveCount(10))
expect(actual) == expected
expect(actual) < expected
expect(flag) == true
expect(myArray.contains('koko')) == true
expect(myArray.count) == 10
https://github.com/Quick/Nimble
@testable import MyAwesomeApp
class MyCalcTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testItCorrectlyAddsTwoNumbers() {
}
func generateNumbers() -> (a: Int, b: Int) {
return (a: randomNum(), b: randomNum())
}
}
Expose your app's public/internal APIs
Runs before each function that starts with "test"
Runs after each function that starts with "test"
A test case!
A helper method in this
test suite
A test suite
import Nimble
@testable import MyAwesomeApp
class MyCalcTests: XCTestCase {
var calc: MyCalc!
override func setUp() {
super.setUp()
calc = MyCalc()
// any additional init setup before each test cases is run
}
override func tearDown() {
super.tearDown()
calc.clearCache()
// any additional teardown before next case is run
}
func testItCorrectlyAddsTwoNumbers() {
let numbers = generateNumbers()
expect(calc.add(numbers.a, numbers.b)) == number.a + numbers.b
}
func generateNumbers() -> (a: Int, b: Int) {
return (a: randomNum(), b: randomNum())
}
}
Run all test suites and all their test cases
Run all the cases in current test suite
Show the test navigator
$ brew install xctool
$ xctool.sh -workspace YourWorkspace.xcworkspace -scheme YourScheme test
$ sudo gem install scan
$ scan --workspace "YourWorkspace.xcworkspace" --scheme "YourScheme" --device "iPhone 6"
func testViewControllerSetsValueOnViewDidLoad() {
let vc = MyViewController()
let _ = vc.view // This triggers viewDidLoad()
expect(vc.someValueSetOnViewDidLoad) == true
}
func testViewControllerSetsValueOnViewDidLoad() {
let s = UIStoryboard(name: "Main", bundle: nil)
vc = s.instantiateViewControllerWithIdentifier("VcStoryboardId") as! MyViewController
let dl = UIApplication.sharedApplication().delegate as! AppDelegate
dl.window = UIWindow(frame: UIScreen.mainScreen().bounds)
dl.window!.rootViewController = UINavigationController(rootViewController: vc)
dl.window!.makeKeyAndVisible()
let _ = vc.view // This triggers viewDidLoad()
}
func testPressingLogoutButtonLogoutsTheUser() {
let vc = MyLoginViewController()
let _ = vc.view
expect(vc.logoutButton).to(beAnInstanceOf(UIButton))
// "tap" the logout button
vc.logoutButton.sendActionsForControlEvents(.TouchedUpInside)
expect(MyAuthManager.sharedInstance.isLoggedIn) == false
}
func testPressingLogoutButtonPresentsUIAlertWarning() {
let s = UIStoryboard(name: "Main", bundle: nil)
vc = s.instantiateViewControllerWithIdentifier("VcStoryboardId") as! MyViewController
let dl = UIApplication.sharedApplication().delegate as! AppDelegate
dl.window = UIWindow(frame: UIScreen.mainScreen().bounds)
dl.window!.rootViewController = UINavigationController(rootViewController: vc)
dl.window!.makeKeyAndVisible()
let _ = vc.view // This triggers viewDidLoad()
expect(vc.logoutButton).to(beAnInstanceOf(UIButton))
// "tap" the logout button
vc.logoutButton.sendActionsForControlEvents(.TouchedUpInside)
// check that view controller presented a UIAlertController
expect(vc.presentedViewController).to(beAnInstanceOf(UIAlertController))
}
Specifying small individual units
integrating the whole system
Unit Tests
Integration Tests
Dirty Hybrids
Good
Good
Bad!
(Unclear goal, high maintainance)
func testColor() {
// given
let dog = Dog(breed: "German Shepherd")
// then
expect(dog.furColor) == UIColor.brownColor()
}
func testGermanShepherdDogBreedHasProperColor() {
// given
let dog = Dog(breed: "German Shepherd")
// then
expect(dog.furColor) == UIColor.brownColor()
}
Good
Bad!