Logo for tanaschita.com

iOS Interview Questions and Answers for Senior Developers Part 6 - Testing

Check your knowledge on automated tests in Swift and iOS

16 Jan 2021 · 8 min read

This post is part of a series

iOS Interview Questions and Answers For Senior Developers

I recently got into the position of leading the technical interviews when my client was hiring a new iOS developer. It's a challenging task to evaluate the skills and knowledge of another developer. In this post, I share the results of my most useful iOS and Swift questions and answers.

The purpose of the interview questions in this part is to get to know the developers knowledge on testing applications with a focus on iOS development.

Dog playing with a frisbee
Some toy testing in action

So let's get started.

1. What is a unit test and how can you write unit tests for an iOS application?

Unit tests are automated tests that validate a piece of code to make sure it behaves as intended.

When you create a project or a target, Xcode includes a unit test target in the scheme that builds the app. Unit tests are written using Apple's XCTest framework. To start writing unit tests, we would create a subclass of XCTestCase and define methods that start with test.

For example, if we were on the Swift development team and we wanted to unit test Swift's joined array method, one of the unit tests could look like this:

func testJoinedTwoWords() throws {
let words = ["Hello", "world"]
let result = words.joined(separator: " ")
XCTAssertEqual(result, "Hello world")
}

2. What is code coverage and when is it useful?

Code coverage indicates the percentage of the code that was executed when running the corresponding unit tests. We can enable code coverage in the target's scheme settings.

While code coverage doesn’t tell us anything about the quality of the unit tests, it is a great way to identify code paths that aren’t tested yet.

3. What is the Given, When, Then style regarding unit tests?

The Given, When, Then style is commonly used to make tests easier to read. The essential idea is to structure the unit test into three parts:

  1. The given part setups the pre-conditions of the test
  2. The when part executes the actions we want to test
  3. The then part validates the outcome

In our example above, we can directly apply this technique.

func testJoinedTwoWords() throws {
// Given
let words = ["Hello", "world"]
// When
let result = words.joined(separator: " ")
// Then
XCTAssertEqual(result, "Hello world")
}

4. When using the XCTest framework, when would we use the setUp() and tearDown() methods?

To reuse data in multiple test methods, we can define them as instance variables in our test case class. We can then use the setUp() method to set up the initial state for each test method and the tearDown() method to clean up after the test is complete.

5. What are mocks and stubs when it comes to writing tests?

Mocking and stubbing are key techniques to manage dependencies and isolate a specific behaviour of the tested object. Replacing the dependencies of the tested object with mocked or stubbed objects makes it more easily to assert and verify outcomes in our tests. Mocks and stubs are testing helpers and not suitable for production.

6. What are performance tests and how can you write performance tests for an iOS application?

With performance tests, we can measure how fast our code runs. The tests also help us identify performance changes as our code base evolves.

To measure how long some code takes to execute we can use XCTest's measure method.

func testNextMovePerformance() throws {
measure {
brain.calculateNextMove()
}
}

On the first run, Xcode establishes a baseline for each performance test and will fail in the future if the performance significantly changes.

7. What is a user interface test and how can you write user interface tests for an iOS application?

User interface tests test the application from the outside, from the user's point of view. UI testing is a great way to ensure that the app's UI interactions keep working as expected while the codebase evolves.

Just like with unit testing, we can use the XCTest framework to write UI tests. The approach is different though, because now we are interacting with the app itself and not with the code.

We do that by using the iOS accessibility system. The XCTest framework provides methods to access and interact with the UI elements e.g. via their accessibility identifier.

func testRegister() throws {
let app = XCUIApplication()
app.launch()
app.buttons["registerButton"].tap()
XCTAssertTrue(app.textFields["nameTextField"].exists)
XCTAssertTrue(app.textFields["emailTextField"].exists)
...
}

8. What is test-driven development (TDD)? What advantages and disadvantages does TDD have in your opinion?

TDD is a development approach where you write a test before implementing the method to pass that test.

This approach mostly leads to better code coverage since testing becomes first priority. If done right, it also leads to a more modularised, structured code. TDD can slow down the development, especially refactoring the code base requires adapting all the tests as well.

9. What is behaviour-driven testing? How would you write behaviour-driven tests in iOS?

In behavior-driven testing, the tests are based on user stories that describe some expected behaviour of the application. Compared to unit tests, behaviour-driven tests are more user- and feature-focused, regardless of implementation details.

For iOS, we can use the third party libraries Quick and Nimble to implement behaviour-driven testing. They allow us to write tests in a way that is closer to our natural language.

describe("a dog") {
let dog = Dog()
context("when the dog is playing with the toy") {
let toy = Toy()
dog.play(with: toy)
it("the toy should not be damaged") {
expect{toy.isDamaged}.to(equal(false)))
}
}
}

10. What is snapshot testing and how can you write snapshot tests for an iOS application?

Snapshot tests make sure that the user interface of the app does not change unexpectedly.

A snapshot test takes a snapshot of a UI element and compares it to a reference snapshot that was stored before. The test will fail if the two snapshots do not match. Either the change is unexpected or the reference snapshot needs to be updated to the new version of the UI element.

There is no native support for snapshot testing in iOS, but there are some third-party libraries like iOSSnapshotTestCase or SnapshotTesting that can be used.

Related tags

Written by

Articles with related topics