Test Helpers used by Stream iOS SDKs for testing purposes. Written in Swift.
In order to use this Swift Package
, you'll need:
- Xcode 11
-
Setup your GitHub account in Xcode 11 (and above) under Preferences-Accounts
-
Add this repo to your Xcode project
https://github.com/GetStream/stream-swift-test-helpers.git
-
Add
StreamSwiftTestHelpers
package to your project's test target as Swift Package Dependency. -
Once correctly added, you should see it in the Project Navigator pane under Swift Package dependencies
-
Start using the
StreamSwiftTestHelpers
by importing them in your test files:import StreamSwiftTestHelpers
, or@_exported import StreamSwiftTestHelpers
to make it accessible target-wise.
This package depends on Difference Swift package, that brings better way to identify what's different between 2 instances. .
This package also depends on SnapshotTesting Swift package, that allows to create snapshot tests.
// Success value
XCTAssertEqual(result, success: "Success Value")
XCTAssertResultSuccess(result)
// Failure
XCTAssertEqual(result, failure: MyError.first)
XCTAssertResultFailure(result)
XCTAssertEqual(MyError.first, .first)
XCTAssertThrowsError(try PathUpdate(with: data), ParsingError.failedToParseJSON)
It's important to not treat the errors as outcasts in our code, but rather make them the first citizens of our API. Testing the errors in Swift is in many occasions a tedious process, the test helpers are here to increase your productivity.
How does it work:
Generic errors in Swift can be compared based on their reflection
public extension Error {
var stringReflection: String {
return String(reflecting: self)
}
}
Let's consider we have declared enum
with this case
public enum DeliveryStatusError: Error, Hashable {
...
case fileSendingIsDisabled(messageId: String?)
...
}
We can leverage the fact the XCTAssertEqual
now contains a test API that allows us to test 2 errors for equality.
If the type of the given error can be inferred, we can leverage the type-safety, which comes with the code-completion for free!
XCTAssertEqual(error, .fileSendingIsDisabled(messageId: "some-long-id"))
Instead of writing code like this
func testItThrowsAnInternalError() {
// given
let myStruct = MyStruct()
// when
XCTAssertThrowsError(try myStruct.runningThisFuncCanThrow(), "It should throw error") { (error) in
// then
switch error {
case let error as MyError:
switch error {
case .internalError:
XCTAssertTrue(true)
default:
XCTFail("It didnt throw an internalError error")
}
default:
XCTFail("It didnt throw MyError, error: \(error)")
}
}
}
You can make use of helper XCTAssertThrowsTypedError
.
func testItThrowsTypedInternalError() {
// given
let myStruct = MyStruct()
// then
XCTAssertThrowsError(try myStruct.runningThisFuncCanThrow(),
MyError.internalError,
"It should throw error")
}
Since the Result
is an enum
in a nutshell, testing the Result
type usually requires you to switch over it's cases to identify the success/failure case of that result.
This can become a burden if you use Result
types a lot.
Instead of writing test like this
func testRequestingTheResourceGivesMeSuccessResult() {
// given
let myStruct = MyStruct()
// when
let result = myStruct.requestSuccessResource()
// then
switch result {
case .success:
XCTAssertTrue(true)
case .failure:
XCTFail("The result is failure")
}
}
you can test the success of Result
like this:
func testSuccessResult() {
// given
let myStruct = MyStruct()
// when
let result = myStruct.requestSuccessResource()
// then
XCTAssertResultSuccess(result)
XCTAssertEqual(result, success: "Succes value")
}
This test will assert of the result is failure
.
Testing the failure result with given error type looks like this
func testFailureResult() {
// given
let myStruct = MyStruct()
// when
let result = myStruct.requestFailureResource()
// then
XCTAssertResultFailure(result)
XCTAssertEqual(result, failure: MyError.internalError)
}
This package provides support for writing UI tests, accessing UI elements and running actions & gestures on them.
This package allows you to build your UI test architecture around two fundamentals concepts - Robot pattern and GIVEN, WHEN, THEN, AND notation.
Hide the UI test implementation detail behind the `Robot.
public protocol Robot: AnyObject {}
You may want to create as many Robot
s as needed to interact with your app during the UI test suite run.
Example:
func testReceiveMessage() throws {
let message = "test message"
let author = "Han Solo"
GIVEN("user opens the channel") {
userRobot.login().openChannel()
}
WHEN("participant sends the message: '\(message)'") {
participantRobot
.startTyping()
.stopTyping()
.sendMessage(message)
}
THEN("the message is delivered") {
userRobot
.waitForParticipantsMessage()
.assertMessageAuthor(author)
}
}