Skip to content

How do i use it

Tyler Thompson edited this page Jul 5, 2021 · 7 revisions

It's important to understand that Cucumber simply provides a way to tie into Gherkin. CucumberSwift is coupled with XCode but does not require a specific kind of target. You can run it with a UI testing bundle, or a Unit testing bundle, whatever makes sense.

To start implementing some step definitions extend Cucumber with the StepImplementation protocol.

import Foundation
import XCTest
import CucumberSwift

extension Cucumber: StepImplementation {
    public var bundle: Bundle {
        class ThisBundle { }
        return Bundle(for: ThisBundle.self)
    }

    public func setupSteps() {
        //Step definitions
        Given("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }

        When("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }

        Then("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }

        // NOTE: You can also re-use the primary keyword that matches this, for example if the And comes After a Given, you'd use Given here.
        And("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }

        But("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }

        MatchAll("Something (matches|matched)") { (matches, _) in
            //assuming match is "Something matched"
            print(matches[0]) //Something matched
            XCTAssert(matches[1], "matched") //true
        }
    }
}

Tables:

There are a couple of different ways of using tables in Gherkin. This is an example of each of the methods and how to tie it together with CucumberSwift

Examples:

Examples let gherkin handle the data for you, individual scenarios are created that iterate over the table and inject the values

Feature: Some terse yet descriptive text of what is desired
        
    Background:
        Given I am logged in
    
    Scenario Outline: <user> logs in # 1st: Dave, 2nd: Bob
        Given a user named <user> # 1st: Dave, 2nd: Bob
            And a password <password> # 1st: hello, 2nd: *%&#*#!!
        When <user> logs in # 1st: Dave, 2nd: Bob
        Then <user> sees an account balance of: <account balance> # 1st: $0, 2nd: $20,000

        Examples:
            | user  | password | account balance |
            | Dave  | hello    | $0              |
            | Bob   | *%&#*#!! | $20,000         |

Steps can be hooked up like normal for example:

var username:String?
var password:String?
//in case you're not regex savvy (.*?) simply matches 0 or more characters, so it'd grab "Dave" in this step the first time and "Bob" the second time
Given("^A user named (.*?)$") { (matches, _) in
    username = matches[1] //1st: Dave, 2nd: Bob
}
And("^A password (.*?)$") { (matches, _) in
    password = matches[1]
}
When("^(.*?) logs in$") { (matches, _) in
    guard let username = username, let password = password else {
        XCTFail("Need a username and password")
    }
    findOrCreateAccount(username)
    login(username: username, password: password)
}
And("^(.*?) sees an account balance of: (.*?)$") { (matches, _) in
    let username = matches[1]
    let balance = matches[2]
    XCTAssertEqual(nameLabel.text, username)
    XCTAssertEqual(accountBalanceLabel.text, balance)
}

Test Data:

Test data can be attached to a step and is handed off to the step implementation to deal with.

    Feature: Some terse yet descriptive text of what is desired
        Scenario: minimalistic
            Given a simple data table
            | foo | bar |
            | boz | boo |

This can be accessed with CucumberSwift with an optional dataTable property on the step object

import Foundation
import XCTest
import CucumberSwift

extension Cucumber: StepImplementation {
    public var bundle: Bundle {
        class ThisBundle { }
        return Bundle(for: ThisBundle.self)
    }

    public func setupSteps() {
        Given("^a simple data table$") { (_, step) in
            let dt = step.dataTable!
            let row = dt.rows[0]
            print(row[0]) //foo
            print(row[1]) //bar
        }
    }    
}