Skip to content

Latest commit

Β 

History

History

swift

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

CI Swift

Swift

Swift testing with XCTest and Cuckoo

Show me the code

Implementation

Sorry but reading that constant and variable names can contain almost any character, including Unicode characters I could not resist πŸ˜… ...

  1. Create HelloMessage class in HelloMessage.swift:
class HelloMessage {
  var πŸ‘‹: String {
    get {
      return "Hello World!"
    }
  }
}
  1. Same way create HelloConsole class in HelloConsole.swift:
class HelloConsole {
  func print(πŸ‘‹: String) {
    Swift.print(πŸ‘‹)
  }
}
  1. Create HelloApp class in HelloApp.swift:
class HelloApp {

  let message: HelloMessage
  let console: HelloConsole

  init(message: HelloMessage, console: HelloConsole) {
    self.message = message
    self.console = console
  }

  func printHello() {
    console.print(πŸ‘‹: message.πŸ‘‹)
  }
}
  1. Create main class in Main.swift that wraps it all together:
@main
public struct Main {
  public static func main() {
    let message = HelloMessage()
    let console = HelloConsole()
    let app = HelloApp(message: message, console: console)
    app.printHello()
  }
}

Test

Following XCTest and Cuckoo guides ...

  1. Mock generation

Mocks have to be generated statically, you can follow these instructions or alternatively:

git clone git@github.com:Brightify/Cuckoo.git /tmp/Cuckoo
/tmp/Cuckoo/build_generator
  • Generate mocks (as many times as needed):
/tmp/Cuckoo/Generator/bin/cuckoo_generator generate \
  --testable Hello \
  --output Tests/Mocks.swift \
  Sources/HelloMessage.swift \
  Sources/HelloConsole.swift

You can also integrate mocks generation in the build, before compile phase.

  1. Test HelloMessage in HelloMessageTest.swift:
final class HelloMessageTest: XCTestCase {
  func testHelloMessageShouldReturnHelloWorld() throws {
    let message = HelloMessage()
    XCTAssertEqual(message.πŸ‘‹, "Hello World!")
  }
}
  1. Test HelloApp in HelloAppTest.swift:
final class HelloAppTest: XCTestCase {
  func testHelloAppShouldDisplayHelloMessage() throws {
    let messageText = "Hello Test!"
    // 2.1 Create a mock of HelloMessage
    let message = MockHelloMessage()
    // 2.2 Return "Hello Test!" whenever πŸ‘‹ getter is called
    stub(message) { stub in
      when(stub.πŸ‘‹.get).thenReturn(messageText)
    }

    // 2.2 Create a mock of HelloConsole
    let console = MockHelloConsole()
    // 2.3 Do nothing whenever print is called
    stub(console) { stub in
      when(stub.print(πŸ‘‹: anyString())).thenDoNothing()
    }

    // 2.4 Create a HelloApp, the one we want to test, passing the mocks
    let app = HelloApp(message: message, console: console)
    // 2.5 Execute the method we want to test
    app.printHello()

    // 2.6 Verify HelloConsole mock print() method
    // has been called once with "Hello Test!"
    verify(console).print(πŸ‘‹: messageText)
  }
}
  1. Test output should look like:
Test Suite 'All tests' started at 2023-12-12 16:48:21.225
Test Suite 'debug.xctest' started at 2023-12-12 16:48:21.227
Test Suite 'HelloAppTest' started at 2023-12-12 16:48:21.227
Test Case 'HelloAppTest.testHelloAppShouldDisplayHelloMessage' started at 2023-12-12 16:48:21.227
Test Case 'HelloAppTest.testHelloAppShouldDisplayHelloMessage' passed (0.003 seconds)
Test Suite 'HelloAppTest' passed at 2023-12-12 16:48:21.230
    Executed 1 test, with 0 failures (0 unexpected) in 0.003 (0.003) seconds
Test Suite 'HelloMessageTest' started at 2023-12-12 16:48:21.230
Test Case 'HelloMessageTest.testHelloMessageShouldReturnHelloWorld' started at 2023-12-12 16:48:21.231
Test Case 'HelloMessageTest.testHelloMessageShouldReturnHelloWorld' passed (0.001 seconds)
Test Suite 'HelloMessageTest' passed at 2023-12-12 16:48:21.232
    Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'debug.xctest' passed at 2023-12-12 16:48:21.232
    Executed 2 tests, with 0 failures (0 unexpected) in 0.004 (0.004) seconds
Test Suite 'All tests' passed at 2023-12-12 16:48:21.232
    Executed 2 tests, with 0 failures (0 unexpected) in 0.004 (0.004) seconds

Run this project using 🐳 docker

  • Execute ./docker-run.sh
  • Once inside the container:
    • Test with swift test
    • Run with swift run
    • Build with swift build -c release
    • Run executable with $(swift build --show-bin-path -c release)/Hello

Run this project locally

Pre-requisites

Run locally

  • Test with swift test
  • Run with swift run
  • Build with swift build -c release
  • Run executable with $(swift build --show-bin-path -c release)/Hello

Create project from scratch

  • Create project using swift package init --name Hello --type executable
  • Customize Package.swift:
    • Add Cuckoo package as a dependency
    • Add HelloTests testTarget with Hello and Cuckoo dependencies