Contact Us

Use the form on the right to contact us.

You can edit the text in this area, and change where the contact form on the right submits to, by entering edit mode using the modes on the bottom right. 


Oak Ridge, TN, 37830
United States

Swift-Snips

Notes on Creating Unit Tests in XCode

Wade Cantley

Common Shortcuts for running a build.

  • CMD + u = Build and run entire suite
  • CTRL + CMD + u = Run Without compiling
  • CTRL + CMD + OPT + u = Build and run tests under cursor (focusses on single test or single file)
  • CMD + SHFT + u = Compile the test suite

Create A new Test file

  • Inherit from XCTestCase
  • Append "test" or "Tests" to the filename.
  • File should ONLY be included in the test target
  • Should move the file under tests.
  • Your test file and functions should show up under the test area.

Using XCTestCase


As mentioned before, "testExample" and "testPerformanceExample" below that would run.

import XCTest

//Added as a reference to the primary target.
@testable import Swift3_TestingExamples

class utilMethodsTests: XCTestCase {
    
    let subject = NSObject() //instantiated for teach 'test' method
    
    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
        
        print("setup")
    }
    
    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
        print("teardown")
    }
    
    func testExample() {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
        
        print("textExample")
        
    }
    
    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
            
            print("Measure")
            
        }
        print("Done measuring")
    }
    
    func test_assertion() {
        
        //subject hasn't had anything added to it so it is indeed Nil and will pass.
        XCTAssertNotNil(subject)
    }
    
    func test_assertion2() {
        
        //Subject will equal itself so this will pass
        XCTAssertEqual(subject, subject)
        
    }
    
}

So, the code "@testable import Swift3_TestingExamples" references classes in the primary build target.


When run, the below is output to the console.

Click on the image to expand it.

Let's break down the results.
Here is the load up of the suite data.

2016-10-19 13:47:02.649662 Swift3_TestingExamples[48598:16495047] subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0

2016-10-19 13:47:02.725485 Swift3_TestingExamples[48598:16495047] subsystem: com.apple.UIKit, category: HIDEventIncoming, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0

2016-10-19 13:47:02.818649 Swift3_TestingExamples[48598:16495046] subsystem: com.apple.BaseBoard, category: MachPort, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0

2016-10-19 13:47:02.908909 Swift3_TestingExamples[48598:16494963] subsystem: com.apple.UIKit, category: StatusBar, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0

2016-10-19 13:47:03.068141 Swift3_TestingExamples[48598:16494963] subsystem: com.apple.BackBoardServices.fence, category: App, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0

Test Suite 'Selected tests' started at 2016-10-19 13:47:03.426

Test Suite 'Swift3_TestingExamplesTests.xctest' started at 2016-10-19 13:47:03.427

 

Test Suite 'utilMethodsTests' started at 2016-10-19 13:47:03.427

Then the first method to run is "testPerformanceExample"
This seemed to loop over the self.measure several times.

Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests testPerformanceExample]' started.
setup

Measure
Measure
Measure
Measure
Measure
Measure
Measure
Measure
Measure
Measure

/Users/chriscantley/Documents/Swift Tutorials/Swift 3/Swift3_TestingExamples/Swift3_TestingExamplesTests/utilMethodsTests.swift:46: Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests testPerformanceExample]' measured [Time, seconds] average: 0.000, relative standard deviation: 119.370%, values: [0.000027, 0.000005, 0.000002, 0.000004, 0.000003, 0.000011, 0.000002, 0.000003, 0.000002, 0.000002], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100

Done measuring
teardown

Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests testPerformanceExample]' passed (0.298 seconds).

The next method to run was "testExample".
As expected, the "Setup" and "teardown" execute around each function. 

Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests testExample]' started.
setup
textExample
teardown
Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests testExample]' passed (0.000 seconds).

Next up was "test_assertion2"

Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests test_assertion2]' started.
setup
teardown
Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests test_assertion2]' passed (0.000 seconds).

Then the last method run was "test_assertion"

Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests test_assertion]' started.
setup
teardown
Test Case '-[Swift3_TestingExamplesTests.utilMethodsTests test_assertion]' passed (0.000 seconds).

Lastly, the suite wrapps up with a total time report and where it saved the test log.

Test Suite 'utilMethodsTests' passed at 2016-10-19 13:47:03.726.
     Executed 4 tests, with 0 failures (0 unexpected) in 0.298 (0.299) seconds

Test Suite 'Swift3_TestingExamplesTests.xctest' passed at 2016-10-19 13:47:03.727.
     Executed 4 tests, with 0 failures (0 unexpected) in 0.298 (0.300) seconds

Test Suite 'Selected tests' passed at 2016-10-19 13:47:03.727.
     Executed 4 tests, with 0 failures (0 unexpected) in 0.298 (0.301) seconds

Test session log:

    /Users/chriscantley/Library/Developer/Xcode/DerivedData/Swift3_TestingExamples-cskiyeuhijxakjepughtltgevngj/Logs/Test/9CC4B557-2C0D-4782-8DA6-854733A07F3C/Session-Swift3_TestingExamplesTests-2016-10-19_134648-IvrJpT.log


Okay, So here is an example of how to connect a Unit Test page to a class.
Below are highlighted pages that we are working with.  

UtilMethods.swift : This has the target method we are testing.
The Unit Test will target "doTheMath()" which is just a simple adding function that spits out an integer.


import Foundation
import UIKit

class UtilMethods: NSObject{
    
    func doTheMath(firstNumber: Int, secondNumber: Int) -> Int {
        
        let addResult =  firstNumber + secondNumber
        return addResult
    }
    
}

UtilMethodsTest.swift : This has the unit test that will evaluate the target method we are testing.


import XCTest
@testable import Swift3_TestingExamples

class UtilMethodsTest: XCTestCase {
    
    //Bring in the target class
    let utilMethods = UtilMethods()
    
    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()
    }

    
    func test_doTheMath() {
        
        let firstInt = 2
        let secondInt = 3
        
        let finalAnswer = 5
        
        //Pass the test data to the method we are testing
        let getResultingNumber = utilMethods.doTheMath(firstNumber: firstInt, secondNumber: secondInt)
        
        //Check that it isn't nil
        XCTAssertNotNil(getResultingNumber)
        
        //Does it give the correct answer
        XCTAssertEqual(finalAnswer, getResultingNumber)
        
        //is the final answer greater than its parts?
        XCTAssertGreaterThan(getResultingNumber, firstInt)
        XCTAssertGreaterThan(getResultingNumber, secondInt)
        
        
        
    }
    
    
}

In this example, all the assertions come back true but once you remove the numbers or remove the calculation within the function, errors start to come back.