Behavior-Driven Development (BDD) in iOS using Swift — Part 3

Nicolas Nascimento
5 min readMay 11, 2020

--

Photo by Max Duzij on Unsplash

Let us work in that UI!

If you are reading this post, it is likely that you read the first part and the second part.

As a refresher, here is the current status of our project:

  • ✅ Augmenting user stories using BDD scenarios;
  • ✅ Coding high-level features using executable specifications;
  • ✅ Coding low-level features using low-level specifications;
  • 🛠 Coding high-level UI features using executable specifications;

Items marked with 🛠 will be covered in this part, while items marked with will be implemented in other parts. Items marked with are already implemented.

In this context, we will continue to develop code for our Weather-App.

Coding high-level UI features using executable specifications

After implementing both high-level and low-level features of our App, it is time to work in the most important part from the perspective of the user, the UI.

For this part, we should use start from our original scenario (see it here), but modify its implementation to use UI interactions.

With this in mind, here is our scenario:

Scenario — Loading forecast successfully for two cities
GIVEN the target cities are San Francisco (SFO) and Porto Alegre (POA)
AND in SFO, it is 20º, “Sunny”, with a min-max of 15º and 25º
AND in POA, it is 15º, “Cloudy”, with a min-max of 10º and 20º
AND the App has started to load the forecast for the target cities
WHEN loading finishes successfully
THEN there should be two cities loaded, SFO and POA
AND the cities should be in alphabetic order
AND it should be 15º, “Cloudy”, with a min-max of 10º and 20º
AND it should be 20º, “Sunny”, with a min-max of 15º and 25º

With this scenario in mind, our design team worked really hard and created an interface for this.

With this, we can begin to write code. We will continue to use the three-step process we have been using so far:

  1. Write a failing test.
  2. Make the test pass.
  3. Refactor.

Step 1 — Writing a failing test

Since we are using the same scenario we have used in the first part of the tutorial, we will replicate the same test which was used there, written with Quick & Nimble, but we will do so in the UI Tests target.

Since we need to launch our App to test its UI, we will write ou testing code inside the "THEN" statement only.

We can use some XCTest directives to simulate the proposed UI.

Done. Our test reflects our expectations, now it is time to actually implement it.

Step 2 — Making the test pass

To make our test pass, we will start with the a simplest implementation possible for the interface, a static UI. We do so using SwiftUI.

This implementation uses a private constant array of forecasts. In addition, it uses SwiftUI components such as NavigationView, and List to get the appearance our design teams wants.

Done! Now we have a test that runs successfully.

Step 3— Refactoring

Although our UI test passes, it still does not use the abstractions we have created previously. So we will update our code and ensure it does just that.

The first modification we should perform is to ensure that the AppState can be used as the driver in a SwiftUI View. This can be done by changing it to a class and making it conform to the ObservableObject protocol. In addition, we should use the property wrapper "@Published" in our properties so that SwiftUI can receive updates from the AppState.

Next, we have to actually make the request for our Forecasts. To keep things simple, we chose to make this request in the SceneDelegate. Here, we will use our two selected cities in our Interactor. In addition, once we the request finishes, we have to update our state property. Finally, we share our State property using environmentObject method in our ContentView.

Next, we make sure our ContentView uses the AppState to build its layout.

A last step is to make sure our tests are still passing. This can be done by handling the "UITESTING" flag we passed when launching the App in our tests.

Done!

Conclusion

We have sucessfully create an entire user story for our App BDD. This last post focused in using BDD when creating UI for our Apps. The main goal of this part is ensuring we use the features we have created previously to drive our UI and that it is aligned with our team's design decisions.

As such, our current status is:

  • ✅ Augmenting user stories using BDD scenarios;
  • ✅ Coding high-level features using executable specifications;
  • ✅ Coding low-level features using low-level specifications ;
  • ✅ Coding high-level UI features using executable specifications;

Finally, I hope you find this guide useful and if you want to continue learning more about BDD, sign up for a complete BDD course in iOS.

Your can take a look at the complete implementation.

Thanks.

Here is a demo of our final App.

--

--