How to Share State Between Scenarios Using Cucumber

Implementation of shared state among cucumber steps in java

Step 1. OrderSelectionStepDef & OrderDetailsStepDef would look like below (please change name as per your implementation)

/**
* Step Definition implementation class for Cucumber Steps defined in Feature file
*/

public class HomePageSteps extends BaseSteps {

TestContext testContext;

public HomePageSteps(TestContext context) {
testContext = context;
}

@When("^User is on Brand Home Page (.+)$")
public void user_is_on_Brand_Home_Page(String siteName) throws InterruptedException {
homePage = new HomePage().launchBrandSite(siteName);
testContext.scenarioContext.setContext(Context.HOMEPAGE, homePage);
}

@Then("^Clicking on Sign In link shall take user to Sign In Page$")
public void clicking_on_Sign_In_link_shall_take_user_to_Sign_In_Page() {
homePage = (HomePage) testContext.scenarioContext.getContext(Context.HOMEPAGE);
signInPage = homePage.ecommSignInPageNavigation();
testContext.scenarioContext.setContext(Context.SIGNINPAGE, signInPage);
}

For your reference

public class BaseSteps {

protected HomePage homePage;
protected PLPPage plpPage;
protected PDPPage pdpPage;
protected ShoppingBagPage shoppingBagPage;
protected ShippingPage shippingPage;

More implementation goes here.....

}

Step 2. Please add below 2 Classes under your framework -

First, Java file name - ScenarioContext.java

public class ScenarioContext {

private Map<String, Object> scenarioContext;

public ScenarioContext(){
scenarioContext = new HashMap<String, Object>();
}

public void setContext(Context key, Object value) {
scenarioContext.put(key.toString(), value);
}

public Object getContext(Context key){
return scenarioContext.get(key.toString());
}

public Boolean isContains(Context key){
return scenarioContext.containsKey(key.toString());
}
}

Second, Java file name - TestContext.java

public class TestContext {

public ScenarioContext scenarioContext;

public TestContext(){
scenarioContext = new ScenarioContext();
}

public ScenarioContext getScenarioContext() {
return scenarioContext;
}
}

Step 3. POM Dependency - picocontainer shall be as per your cucumber version

   <dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
</dependency>

Hope this helps.

Java RestAssured Cucumber - sharing variable value between scenarios in the same class

It is intentionally difficult to share information between scenarios. Each scenario is it's own little experiment and should not be influenced by others.

Now if you're used to writing manual test scripts you may think it's efficient to reuse things. And it is. But a computer is much faster so you don't have to be efficient. Rather because it's cheap to do everything from scratch, a little inefficiency is worth reducing the chance tests can interact by accident.

So rather consider writing three different scenarios:

Scenario: Create
Given the things needed to make a category
When a new category is created
Then it has all the things used to make it

Scenario: Update
Given a category with some property
When the property of the category is changed
Then fetching the category again shows the updated
property

Scenario: Delete
Given a category
When the category is deleted
Then the category is not found when fetched

The second and third create the category in the given step.

Now if this is a system that isn't shutdown after a test run you may also want to use after hooks to try and delete any categories created when the test is done.

How to make a scenario that depends on another scenario using cucumber, selenium and java

Take a look into cucumber hooks, this allows you to set up global 'before' and 'after' steps, which will run for every scenario without having to specify them in your feature files.

Because they run for every scenario, they're ideal for something like initialising the driver at the start of each test. It may be suitable for running your logon, but if there's a chance you'll have a scenario which doesn't involve logging on then it wouldn't be the way to go (alternative further down). The same applies for the after scenario, which is where you could perform the log off and shut down your driver. As an example:

/**
* Before each scenario, initialise webDriver.
*/
@Before
public void beforeScenario() {
this.application.initialiseWebDriver();
}

/**
* After each scenario, quit the web driver.
*/
@After
public void afterScenario() {
this.log.trace("afterScenario");
this.application.quitBrowser();
}

In my example, I'm simply starting the driver in the before scenario, and closing it in the after, But in theory these before and after methods could contain anything, you just need to have them in your step definitions class and annotate them with the '@Before' and '@After' tags as shown.

As well as these, you can also have multiple before and after tags which you can call by tagging the scenario. As an example:

/**
* Something to do after certain scenarios.
*/
@After("@doAfterMethod")
public void afterMethod() {
this.application.afterThing();
}

You can set up something like this in your step defs, and as standard it won't run. However, you can tag your scenario with '@doAfterMethod' and it will run for the tagged scenarios, which makes this good for a common scenario that you will need at the end of tests, but not all of them. The same would work for methods to run before a scenario, just change the '@After' to '@Before'.

Bear in mind that if you do use these, the global Before and After (so in this example the driver initialisation and quitting) will always be the first and last things to run, with any other before/afters in between them and the scenario.

Further Reading:
https://github.com/cucumber/cucumber/wiki/Hooks
https://zsoltfabok.com/blog/2012/09/cucumber-jvm-hooks/



Related Topics



Leave a reply



Submit