26
Xcode testing Using XCTest

Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Embed Size (px)

Citation preview

Page 1: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Xcode testingUsing XCTest

Page 2: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing in XCode

Done using XCTest class

Test classes are created separately from code

Test classes can access and call classes in your app

Test classes have assertion functions that you can call to test results

You can define how fine-grain your tests are.

Page 3: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Test Navigator

Create a new single-view project.

Click on the test navigator button in the left panel

You’ll see two templates for testing

Page 4: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Test NavigatorThe Run button ( ) appears to the right of the item name when you hold

the pointer over any item in the list.

This is a quick way to run all the tests in a bundle, all the tests in the class,

or any individual test.

Tests return pass or fail results to Xcode.

As tests are being executed, these indicators update to show you the

results, a green checkmark for pass or a red x for fail.

In the test navigator shown here, two of the tests have asserted a failure.

Page 5: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Test NavigatorClicking any test class or test method in the list opens the test class in the

source editor.

Test failures display the result string at the associated assertions in the

source editor.

Page 6: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

TestingIn the test navigator in the single-view application that you created earlier, click on the class testExample()

In the editor, you’ll see the code:

import UIKitimport XCTest

class testingInSwiftTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() }

Continued on next slide…

Page 7: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. self.measureBlock() { // Put the code you want to measure the time of here. } } }

Click on the run button that appears next to testExample() when you put your mouse over it.

This is an assertion that always passes

The green check means test was passed

Page 8: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Test OrganizationThe setUp method gets called before each test runs.

If you have initialization code you call before running each test, place the code in the setUp method so you don’t have to repeat the code in each test.

The tearDown method gets called after each test runs. If you run any cleanup code after running each test, place that code in the tearDown method so you don’t have to repeat the code in each test.

The testExample method provides an example of a test method.

The testPerformanceExample method provides an example of a performance test case, which measures how long a task takes to complete.

Page 9: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Test Methods

A Swift test method has the following conditions:

It must begin with the word test.

It takes no arguments.

It returns no value.

You can create as many test methods in a class as you like.

Every test method must have an assertion which determines whether or not the test is passed.

Page 10: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Assertions

XCTest assertions start with XCTAssert. If you start typing XCTAssert, Xcode’s code completion should show you a list of all the available assertions

The following are the most widely-used assertions:XCTAssertNotNil asserts a variable is not nil.

XCTAssertTrue asserts a condition is true.

XCTAssertFalse asserts a condition is false.

XCTAssertEqual asserts two values are equal.

XCTAssertEqualObjects asserts two objects are equal.

XCTAssertEqualWithAccuracy asserts two floating-point values are equal.

Page 11: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

AssertionsXCTest assertions take two or more arguments.

The first arguments depend on the assertion. XCTAssertTrue and XCTAssertFalse take a condition as the first argument.

The XCTAssertEqual assertions take two arguments at the start: the two items you’re checking are equal.

After the assertion testing arguments comes the error message, which is a string.

Xcode displays the error message if the assertion fails.

If you want to show the value of a variable in the error message, place the variable name in parentheses in the error message, prefixed by a backslash character.

\(variableName)

The following code shows an example of an assertion involving a variable named length:

XCTAssertTrue(length == 12, “The length should have been 12. Actual length: \(length)")

Page 12: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing

Add the following method to the testExample() class.

Run the testExample()

func testMultiplyingTwoNegativeNumbersYieldsAPositiveValue() { let x = –6 let y = –4 let product = x * y XCTAssertTrue(product > 0, "Multiplying two negative numbers should yield a positive number. Product: \(product)") }

This test does not test the code in the app but only serves to demonstrate how assertions work

Page 13: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing II

Create the following view in your app

Add and connect the following IBOutlets:

@IBOutlet weak var addButton: UIButton! @IBOutlet weak var resultText: UITextField! @IBOutlet weak var secondText: UITextField! @IBOutlet weak var firstText: UITextField!

Page 14: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing IIAdd the following code to the viewController

@IBAction func addButtonPressed(sender: UIButton) { // toInt returns optional that's why we used a:Int? let a:Int? = firstText.text.toInt() // firstText is UITextField let b:Int? = secondText.text.toInt() // secondText is UITextField // check a and b before unwrapping using ! if a != nil && b != nil { var ans = a! + b! resultText.text = "\(ans)“ } else { resultText.text = "Input values are not numeric" } }

connect the button in the storyboard to this IBAction method

Page 15: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing II

Go to the Project Navigator and click on the file ViewController.swift

Then click on the File Inspector on the rightmost panel and add the ViewController to the test target

Do the same with the AppDelegate.swift file

This enables methods in the test file to see variables in the viewController

Page 16: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing II

Go to your test class

At the top add the line

import testingInSwift

Where testingInSwift is the name of your project.

Page 17: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing IIFirst determine whether the root view loads:

func testViewDidLoad()

{

// we only have access to this if we import our project above

// Viewcontroller is the name of the root view controller class in your app

let v = ViewController()

// assert that the ViewController.view is not nil

XCTAssertNotNil(v.view, "View Did Not load")

}

}

Page 18: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

It’s easy to test your models.

It’s tricky to test your storyboard.

First stepsGo to the project navigator on the left (where the classes in your project are listed).

Click on your project name

Go to the Build Settings tab

Go to the Packaging section

Change Defines Module to “YES”

Note the Product Module Name several lines below this; this name is what you’ll need to import into your test class

Page 19: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

Go to your test class and import the product module name:

import testingInSwift

class testingInSwiftTests: XCTestCase {

Add this line but substitute your product module name

Page 20: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

Manual Lifecycle eventswhen your app runs, lifecycle events are generated automatically (viewWillAppear, viewDidLoad, etc.)

in tests, you will need to generate these in code

Page 21: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

First, need to give your storyboard a name.In the project navigator, go to the Main.storyboard (this app only has one storyboard; some apps have more)

In the storyboard navigator, click on the view controller

Then open the identity inspector in the right side panel

Give the storyboard an identifier

Page 22: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

Now we can write a test method to test our interface.

go to your test class and add the following method (can be anywhere in the class):

func testAddMethod() {

let SB = UIStoryboard(name: "Main", bundle: nil)

myVC = SB.instantiateViewControllerWithIdentifier("testStoryboard") as ViewController

let _ = myVC.view

// more code goes here

}

We’ll examine each of these lines on the next slide

Page 23: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

func testAddMethod() {

let SB = UIStoryboard(name: "Main", bundle: nil)

myVC = SB.instantiateViewControllerWithIdentifier("testStoryboard") as ViewController

let _ = myVC.view

// more code goes here

}

First we create an instance of the storyboard

Then we instantiate the viewcontroller for this storyboard (note the “as ViewController). The variable myVC now points to the viewcontroller.

The IBOutlets are only created when the view loads, so we create a blank variable that contains the view, thus forcing the view to load.

Page 24: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

We can now populate the fields and click the button.

Add this code after the “more code goes here “ comment on the previous slide:

let sumText = “–10“ // this is the expected answer

myVC.firstText!.text = “–6" // Now set values in the textfields

myVC.secondText!.text = “–4"

Page 25: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Testing III

Now click the button

myVC.addButton!.sendActionsForControlEvents(UIControlEvents.TouchUpInside)

and then test the answer

XCTAssertEqual(sumText, myVC.resultText!.text, "Adding two numbers should yield \(sum)")

}We’re getting the answer out of the result textfield

Now you can run the test!

This is the string containing the expected answer

This is the IBOutlet to the button

Page 26: Xcode testing Using XCTest. Testing in XCode Done using XCTest class Test classes are created separately from code Test classes can access and call classes

Implementing the test plan

Every test in the plan should have a method that implements that test