Skip to content

Creating your own steps

José Fernández edited this page Jan 9, 2021 · 35 revisions

All steps included in Gingerspec were created with the idea of reusability and flexibility. The problem is, that in order to achieve this, the steps must be low level enough to be used for a wide range of cases. You can, create your own steps with the level of abstraction that you prefer, however, I would like you to consider the following points before trying to apply BDD with GingerSpec:

  • GingerSpec was designed to work as a DSL for the creation of integration tests. There are several reason to keep the legacy of Given-When-Then, like making the tests more readable, and its integration wit current IDEs.

  • GingerSpec is, in itself, a super-simplified programming language that heavily borrows BDD syntax.

  • Cucumber, when used outside of its intended scope (collaboration at the beginning of the development process), becomes in no more than a simple wrapper between integration tests.

  • You can create your own steps and just call GingerSpec methods behind the scenes using the GingerSpec API. This may make sense for UI testing, but in other contexts like REST Api testing, where what is under test is a contract and not a behaviour, this make little sense. You might be better of just using something like REST-assured instead.

Creating your own steps

Creating your own step logic

of course, there will be times when the given task cannot be accomplished using merely the steps contained in Gingerspec. For such cases, you can, in the same way as above, create your step definition and start typing your custom logic using Java code

    @Given("^I verify the Interactions and Widgets sections are present$")
    public void iVerifyTheInteractionsAndWidgetsSectionsArePresent() throws Throwable {
        /**
         * Write your java code here
         */
    }

Merging low-level steps

This could certainly be the easiest way in the sense that you can just reuse the steps already contained in Gingerspec and group several of them to create a single and more high-level step

Consider the following scenario as an example. the scenario contains 4 low-level GingerSpec steps. It can be converted from this:

    Scenario: Verify that there are two main sections "Interactions" and "Widgets"
        Given My app is running in 'demoqa.com:80'
        And I browse to '/'
        When '2' elements exists with 'class:widget-title'
        And I wait '1' seconds

To this:

    Scenario: This is the same scenario as above, but in one line, using custom steps
        Given I verify the Interactions and Widgets sections are present

To accomplish this, you will have to first create the new step definition and just call the underlying java functions for the low-level steps with the correct parameters, like this:

    @Given("^I verify the Interactions and Widgets sections are present$")
    public void iVerifyTheInteractionsAndWidgetsSectionsArePresent() throws Throwable {
        seleniumGSpec.setupApp("demoqa.com:80");
        seleniumGSpec.seleniumBrowse(null,"/");
        seleniumGSpec.assertSeleniumNElementExists("at least", 2,"class","widget-title");
        utilsGSpec.idleWait(1);
    }

Remember that the java class where you create your new steps definitions must be included in the glue parameter in the runner class.

Since hunting down the underlying functions and parameters of all steps in a scenario can be a long and painstaking process, GingerSpec provides a feature that makes this process much easier. Run your tests with the -DSHOW_STACK_INFO and you will get information about the underlying java function and parameters that are being called for each gherkin step

Example:

mvn verify -Dit.test=eu.vptech.firstProject.tribe1.CucumberSeleniumIT -DSHOW_STACK_INFO

Output:

  Scenario: Verify that there are two main sections "Interactions" and "Widgets" # src/test/resources/features/tribe1/cucumber_selenium_test.feature:19
    Given My app is running in 'demoqa.com:80'
         # SeleniumGSpec.setupApp(String)
         # Argument 0: demoqa.com:80
    And I browse to '/'
         # SeleniumGSpec.seleniumBrowse(String,String)
         # Argument 0: null
         # Argument 1: /
    When '2' elements exists with 'class:widget-title'
         # SeleniumGSpec.assertSeleniumNElementExists(String,Integer,String,String)
         # Argument 0: null
         # Argument 1: 2
         # Argument 2: class
         # Argument 3: widget-title
    And I wait '1' seconds
         # UtilsGSpec.idleWait(Integer)
         # Argument 0: 1

Where:

Given My app is running in 'demoqa.com:80' -> Step being executed
         # SeleniumGSpec.setupApp(String)  -> Underlying Java method being executed and the type of each parameter 
         # Argument 0: demoqa.com:80       -> Value of first parameter

-DSHOW_STACK_INFO is only available in Gingerspec 2.0.3 and up