Android Dev peep on iOS Unit Test

Image for post
Image for post

As an Android Developer, if you are curious about iOS unit test and it’s setup, this would be for you. In this blog, I will show you how to import the Quick and Nimble test framework (a popular Behavior Driven Test for iOS) as well as the XCode provided XCTestCase

Pre-requitesite

I would not touch on open XCode and setup a basic project. You could refer to my previous blog for that.

But if you just like to know the term, but not actual hands on, just read on. Don’t worry about starting it on XCode.

Cocoapods — the Gradle of iOS

In Android Studio, we are bless to have Gradle embedded in Android Studio, so that import external libraries is made so easy.

However in XCode, life is harder. The Cocoapods doesn’t come with it.

One have to go to terminal and install the Cocoapods if it need to import libraries (which is called Pods for iOS).

To get Cocoapods install, type the following command in terminal (obviously on Mac machine)

sudo gem install cocoapods

Import Pods (Library) to your project

To import library to your project, you’ll need to first

  • Run pod init in the project folder to generate all the pod files.
  • Add the needed pods (in our case Quick and Nimble pods) to Podfile
  target 'yourprojectTest' do
inherit! :search_paths
# Pods for testing
pod "Quick"
pod "Nimble"

end

Note: by default XCode provide us a test framework named XCTestCase, but I’ll be showing you also another way of testing (Behavioral Driven Test) that is commonly used by iOS developer

  • Run pod` install to download the Quick and Nimble pods to your project
  • Open the yourproject.xcworkspace, you’ll see the Quick and Nimble has been added to the project
Image for post
Image for post

XCTestCase — JUnit like test in iOS

When you create a project in iOS, this is given to you be default.

The test class given is as below.

import XCTest
@testable import yourproject
class yourprojectTests: XCTestCase {

override func setUp() {
super.setUp()
}

override func tearDown() {
super.tearDown()
}

func testExample() {
// This is an example of a functional test case.
// Use XCTAssert to verify your tests produce.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

This looks very familiar with JUnit, as it has setup() and teardown().

For each test, just need to prefix the test keyword on the function name, it would be a test function. If it is not prefix with test, it would be a normal function. No annotation needed.

There’s one very interesting item there, which is self.measure, where any code that is place under this function, will have it’s execution performance measured.

In Kotlin, you could use the following function to measure time

measureNanoTime { /**Code to measure time**/ }

To execute the test, just like Android Studio, click on the green check box on the left (on top of the line number), or use Command+u

Image for post
Image for post

P/S: I try to run individual test function, it always execute the entire class instead.

What is Quick & Nimble?

It’s a Swift and Objective-C Testing Framework, that is popular among iOS community, partly due to the more powerful matcher (by Nimble) and also it support Behavior Driven Test (by Quick).

What’s Behavior Driven Test

There’s a lot of site out there give a good description on it, but I’m going to simplify it by stating, it is basically breaking your test into 3 categories i.e.

  1. Given (what’s the condition)
  2. When (what’s the action)
  3. Then (what’s the expected result)

In Android JUnit Test, you could do it as below…

@Test
fun `given some condition when trigger action then expect result`() {
// Given
whenever(testMock()).thenReturn(fixedMockedValue)

// When
testClass.testTrigger()

// Then
verify(testObject).testExpectCall()
}

The iOS Way

With Quick and Nimble, iOS has a framework that allow one to describe the test, better using the describe, context and it functions that was provided by Quick as could be seen below.

import Foundation
import Quick
import Nimble
@testable import yourproject
class myTestSpec: QuickSpec {
override func spec() {
beforeEach { /** Code execute for every Describe **/ }
describe("Given some condition") {
beforeEach { /** Code execute for every Context **/ }
context("When some action") {
beforeEach { /** Code execute for every It **/ }
it("Then some expected result") {
expect(true).to(beTrue())
}
} }
}
}

Several notes:

  • You’ll need to have the @testable import yourProject to enable access to your project classes for test.
  • You’ll need to inherit from the QuickSpec protocol so that we could write the spec function detail.
  • There could be more than one describe, context and it, to allow multiple test scenarios, test actions or test results triggered, yet individually is evaluated as a unit.
  • The beforeEach is to encapsulate the code that needed on it’s designated scope (i.e. describe, context or it). This is similar to setup but more powerful as it could have a different level scope of setup.

There are several good tutorial out there on it. Below is one

With this, hopes this provide some insight of how iOS perform Unit Test. It’s always interesting to know how the other part of the world function.

I hope this post is helpful to you. You could check out my other interesting topics here.

Follow me on medium, Twitter or Facebook for little tips and learning on Android, Kotlin etc related topics. ~Elye~

Written by

Passionate about learning, and sharing mobile development and others https://twitter.com/elye_project https://www.facebook.com/elye.proj

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store