UserBehaviorDrivenTestKit - A Swift framework simplifying UITests by adopting a user-behavior driven pattern.
UBDTestKit aims to make writing UITests more intuitive, efficient, and fun by focusing on user intentions and serialization of interactions into a clear and readable series of actions on associated elements.
- Enhanced Readability: Describe tests in a human-readable and intuitive format.
- Increased Maintainability: Encourages reuse and easy addition of new actions or elements.
- Reduced UI Dependence: Minimizes the influence of updates to internal XCUIElement implementation on the tests.
- In Xcode, select "File" -> "Add Packages..."
- Paste the git URL (
https://github.com/peteranny/UserBehaviorDrivenTestKit.git
) in the search box - Follow the on-screen instructions to add the dependency
- Include
import UBDTestKit
at the top of your Swift files to start using the framework
First off, define the elements that user interacts with in the app:
import UBDTestKit
enum ExampleElement {
case landingScreen(LandingScreenElement)
enum LandingScreenElement {
case this
case loginButton
case welcomeAccount
}
case loginScreen(LoginScreenElement)
enum LoginScreenElement {
case this
case accountField
case passwordField
case submitButton
}
}
Secondly, conform to UBDElement
to interpret the elements under the hood:
import UBDTestKit
import XCTest
extension ExampleElement: UBDElement {
func resolve() -> UBDResolvedElement {
let app = XCUIApplication()
switch self {
case .landingScreen(.this):
return .from(app.buttons["Log In"])
case .landingScreen(.loginButton):
return .from(app.buttons["Log In"])
case .landingScreen(.welcomeAccount):
return .from(app.staticTexts["welcome.label"],
value: { String($0.label.trimmingPrefix("Welcome back, ")) })
case .loginScreen(.this):
return .from(app.staticTexts["Enter You Information"])
case .loginScreen(.accountField):
return .from(app.textFields["account"])
case .loginScreen(.passwordField):
return .from(app.secureTextFields["password"])
case .loginScreen(.submitButton):
return .from(app.buttons["Submit"])
}
}
}
Finally, subclass UBDTestCase
to start writing your test in a user-behavior driven flow:
import UBDTestKit
final class ExampleUITests: UBDTestCase<ExampleElement> {
func testExampleUserBehaviorDriven() throws {
then(.launch)
then(.wait(for: .landingScreen(.this), to: .appear))
then(.tap(on: .landingScreen(.loginButton)))
then(.wait(for: .loginScreen(.this), to: .appear))
then(.tapToEnter("P.S@g.com", on: .loginScreen(.accountField)))
then(.tapToEnter("888888", on: .loginScreen(.passwordField)))
then(.tap(on: .loginScreen(.submitButton)))
then(.wait(for: .loginScreen(.alert(.incorrect)), to: .appear))
then(.tap(on: .loginScreen(.alert(.okButton))))
then(.tapToEnter("000000", on: .loginScreen(.passwordField)))
then(.tap(on: .loginScreen(.submitButton)))
then(.wait(for: .loginScreen(.this), to: .disappear))
then(.wait(for: .landingScreen(.welcomeAccount), to: .haveValue("P.S@g.com")))
}
}
To group a series of basic action into an extended action, please refer to Extend Actions for the guidance.
To learn more about the user-behavior driven pattern, visit this article for more information.
This framework comes with a demo app that shows more usage of the framework. To run the demo:
- Open the
UserBehaviorDrivenUITestsExample
project in Xcode - Go to
ExampleUITests.swift
in the project navigator - Run the tests to observe how the UITests are accomplished using actions defined in UBDTestKit
The code of the demo provides a useful guide for developers on how to structure their UITests using UBDTestKit, so be sure to check it out.