iOS Testing
TDD
BDD
Integration Testing
Acceptance Testing

iOS Tests/Specs TDD/BDD and Integration Acceptance Testing

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

TDD, BDD, integration testing, and acceptance testing are often discussed as if they were rival approaches. They are not. TDD and BDD mostly describe how tests are written and framed, while integration and acceptance testing describe how much of the system a test exercises. A strong iOS test strategy uses several of these ideas together.

Separate Style from Scope

A useful mental model is this:

  • TDD means writing a failing test before the implementation
  • BDD means naming and structuring tests around observable behavior
  • integration tests verify collaboration between components
  • acceptance tests verify user-visible outcomes through the app interface

This distinction matters because teams often waste time arguing about labels instead of building the right mix of tests.

Use TDD Where Logic Is Cheap to Isolate

TDD works best for domain logic that is deterministic and does not require heavy UI setup.

swift
1import XCTest
2
3struct DiscountEngine {
4    func finalPrice(subtotal: Double, isMember: Bool) -> Double {
5        let discount = isMember ? 0.10 : 0.0
6        return subtotal * (1.0 - discount)
7    }
8}
9
10final class DiscountEngineTests: XCTestCase {
11    func test_givenMember_whenCalculatingFinalPrice_thenAppliesTenPercentDiscount() {
12        let engine = DiscountEngine()
13        let result = engine.finalPrice(subtotal: 200, isMember: true)
14        XCTAssertEqual(result, 180, accuracy: 0.0001)
15    }
16}

This kind of test is fast, cheap, and ideal for running on every change.

BDD Naming Improves Readability

You do not need a separate framework to get many of the benefits of BDD. In XCTest, descriptive names already help tests read like executable specifications.

swift
1import XCTest
2
3final class LoginPolicy {
4    func canLogin(email: String, password: String) -> Bool {
5        !email.isEmpty && password.count >= 8
6    }
7}
8
9final class LoginPolicySpecs: XCTestCase {
10    func test_givenShortPassword_whenValidatingLogin_thenReturnsFalse() {
11        let policy = LoginPolicy()
12        let allowed = policy.canLogin(email: "[email protected]", password: "123456")
13        XCTAssertFalse(allowed)
14    }
15}

The biggest value here is communication. A good test name explains the business expectation better than an internal wiki sentence.

Add Integration Tests at Real Boundaries

Unit tests do not catch wiring problems between networking, decoding, persistence, and business rules. That is where integration tests help.

swift
1import XCTest
2
3struct Profile: Codable, Equatable {
4    let id: Int
5    let displayName: String
6}
7
8final class ProfileRepository {
9    func decodeProfile(data: Data) throws -> Profile {
10        try JSONDecoder().decode(Profile.self, from: data)
11    }
12}
13
14final class ProfileRepositoryIntegrationTests: XCTestCase {
15    func test_decodesProfilePayloadFromServerContract() throws {
16        let json = """
17        {
18          "id": 42,
19          "displayName": "Ari"
20        }
21        """
22        let data = try XCTUnwrap(json.data(using: .utf8))
23
24        let repository = ProfileRepository()
25        let profile = try repository.decodeProfile(data: data)
26
27        XCTAssertEqual(profile, Profile(id: 42, displayName: "Ari"))
28    }
29}

This kind of test is still fast, but it covers collaboration instead of only one isolated function.

Keep Acceptance Tests Narrow and Valuable

Acceptance tests in iOS are usually written with XCUITest and exercise the app the way a user would. They are slower and more brittle, so they should focus on critical flows.

swift
1import XCTest
2
3final class CheckoutAcceptanceTests: XCTestCase {
4    func test_userCanCompleteCheckoutFlow() {
5        let app = XCUIApplication()
6        app.launch()
7
8        app.buttons["catalog_first_item"].tap()
9        app.buttons["add_to_cart"].tap()
10        app.buttons["open_cart"].tap()
11        app.buttons["checkout"].tap()
12
13        XCTAssertTrue(app.staticTexts["order_success_title"].waitForExistence(timeout: 5))
14    }
15}

These tests are expensive, so they should cover revenue paths, login flows, and other behaviors that truly justify end-to-end confidence.

Build a Practical Test Mix

A healthy iOS project usually has:

  • many fast unit tests
  • a smaller number of targeted integration tests
  • a very selective set of UI acceptance tests

That gives good feedback speed without pushing every change through a huge slow UI suite.

Common Pitfalls

A common mistake is treating TDD and BDD as separate layers of testing instead of writing styles that can apply at several layers.

Another pitfall is putting too much business verification into UI tests. That makes the suite slower and more fragile than necessary.

Teams also often chase coverage percentages instead of coverage of meaningful risk. A hundred trivial tests do not replace a few well-chosen integration and acceptance tests.

Finally, naming tests after implementation details makes refactoring painful. Prefer behavior-focused names so tests remain useful even when internals change.

Summary

  • TDD and BDD describe how tests are written, while integration and acceptance tests describe scope.
  • Use TDD heavily for fast, isolated logic.
  • Use BDD-style naming to make tests readable and behavior-focused.
  • Add integration tests at important boundaries such as decoding, persistence, and service wiring.
  • Keep acceptance tests narrow and focused on critical user-visible flows.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.