Quick and Nimble

In another words Quick is a framework for creating BDD tests that comes with Nimble that can help to provide more clear expectations for your tests.

The Example

The example will be an iOS app written in Swift 1.2, named Pony. The app has a tab-bar and a view controller as the app intro that will be prompted when the app starts, the Main.storybard look like this:

and running:

Th

Loaded.

Intro is prompted.

Setting up Quick and Nimble on Pony app

If you have the latest CocoaPods version installed, you just have to add them in the Podfile:

CocoaPods: “Pods written in Swift can only be integrated as frameworks; this feature is still in beta…” so you should add use_frameworks!

Testing

PonyTabController: UITabBarController

PonyTabController is a UITabController subclass that is responsible for presenting the app intro if it hasn’t already and dismiss-it if the delegate is called.

Let’s start with our first expectation on viewDidAppear:

“When app intro had never been dismissed it should be set as the appIntroDelegate”

Our first spec:

Now we have the expectation described but there are some things missing, there is no assertion or setup for the object that we want to test (an instance of PonyTabController) and it is not being invoked by any method. In order to setup that more clearly we can divided the test code into three groups: Arrange, Act, Assert, for example:

Arrange:

Create a instantiate a PonyTabController.

Act:

Trigger the instance of the PonyTabController lifecycle .

Assert:

tabController should be the appIntroViewController delegate

resulting:

Now a fully working test ☺

Organising the test code on this way its best known as the: “Arrange-Act-Assert” pattern and some benefits are:

Clearly separates what is being tested from the setup and verification steps.

Clarifies and focuses attention on a historically successful and generally necessary set of test steps.

Now doing the same for:

“When app intro had never been dismissed it should be presented”

and

“When app intro had never been dismissed and appIntroDidFinishiscalled it should dismiss app intro”

Little brief about “describe” and “context”:

Describe: wrap a set of tests against one functionality

Context: wrap a set of tests against one functionalityunder the same state.

Extra

Nimble comes with the function waitUntil where you can execute something inside it closure and call done() when is ready, if done() is not called within a second the test will fail, if you need to extend that interval the function accepts a timeout parameter where you can specify for how long the function will wait until it fails. It could be handy when you want to wait for a view controller to be presented, e.g:

Concluding

You can use Quick and Nimble to help you achieve more meaningful tests with clearer expectation.

There is a lifecycle that must be followed, i.e: you can’t present a view controller if there another already being presented or the view is not part of the hierarchy.

UIKit provide public methods to help trigger view controller states.

Testing on view controllers can be tricky sometimes, try to keep them thin as possible ☺