rogervinas / tests-everywhere
🤠 Tests, Tests Everywhere!
Swift testing this simple Hello World 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!"
}
}
}
2) Same way create HelloConsole
class in HelloConsole.swift:
class HelloConsole {
func print(👋: String) {
Swift.print(👋)
}
}
3) 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.👋)
}
}
4) 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:
- Build generator (only once, XCode command line tools required):
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.
2) Test HelloMessage
in HelloMessageTest.swift:
final class HelloMessageTest: XCTestCase {
func testHelloMessageShouldReturnHelloWorld() throws {
let message = HelloMessage()
XCTAssertEqual(message.👋, "Hello World!")
}
}
3) 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)
}
}
4) 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
Happy Testing! 💙
Top comments (0)