Cucumber hook allows us to better manage the code workflow and helps us to reduce the code redundancy. We can say that it is an unseen step, which allows us to perform our scenarios or tests.
To understand this notion better, let’s take an example of a feature file and a step definition file.
The highlighted portion in the given statement actually does the job of setting up the webdriver and ending the webdriver session. So, it is actually not relevant to the essence of “Given statement”, and it is more like a setup for the test. Also if we think with a broader prospective, then in case of multiple scenarios for this feature, this webdriver setup and cleanup will run with each given statement. Logically, it makes sense to have the setup and cleanup executed only once.
So to bring optimization, hooks can be utilized. More often we use two types of hooks: “Before” hook and “After” hook. Method/function/piece of code, defined within Before and After hooks, always run, even if the scenario gets passed or failed.
As the name suggests, before hook gets executed well before any other test scenarios, and after hook gets executed after executing all the scenarios.
Hooks are defined within the step definition file only.
Let’s automate an example of before and after hook.
Step 1 − Create Maven project as hookTest, add necessary dependency in pom.xml.
Step 2 − Create a Java package named as hookTest under src/test/java
Step 3 − Create a step definition file named as hookTest.java under the package.
package hookTest; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import cucumber.annotation.en.Given; import cucumber.annotation.en.Then; import cucumber.annotation.en.When; public class hookTest { WebDriver driver = null; @Before public void setUp(){ driver = new FirefoxDriver(); } @Given("^user navigates to facebook$") public void goToFacebook() { driver.navigate().to("https://www.facebook.com/"); } @When("^I enter Username as \"([^\"]*)\" and Password as \"([^\"]*)\"$") public void I_enter_Username_as_and_Password_as(String arg1, String arg2) { driver.findElement(By.id("email")).sendKeys(arg1); driver.findElement(By.id("pass")).sendKeys(arg2); driver.findElement(By.id("u_0_v")).click(); } @Then("^login should be unsuccessful$") public void validateRelogin() { if(driver.getCurrentUrl().equalsIgnoreCase( "https://www.facebook.com/login.php?login_attempt=1&lwv=110")){ System.out.println("Test Pass"); } else { System.out.println("Test Failed"); } driver.close(); } @After public void cleanUp(){ driver.close(); } }
Step 4 − Create a feature file named “hookTest.feature” under the package.
Feature − Scenario Outline.
Scenario Outline − Hook Test
Given user navigates to Facebook
When I enter Username as "<username>" and Password as "<password>"
Then login should be unsuccessful
| username | password | | username1 | password1 |
Step 5 − Create a runner class file.
Create the runner class as runTest.java inside the package dataTable (see the section scenario outline for more detailed steps).
Write the following code.
package hookTest; import org.junit.runner.RunWith; import cucumber.junit.Cucumber; @RunWith(Cucumber.class) @Cucumber.Options(format = {"pretty", "html:target/cucumber"}) public class runTest { }
Save the file.
Run the test using option −
Select runTest.java file from the package explorer.
Right-click and select the option, Run as.
Select JUnit test.
So now when we run this, following will be the sequence of execution.
Before hook − Set up the webdriver and other prerequisites to run the test.
Given statement
When statement
Then statement
After hook − Close the webdriver and do the cleanup process.
We can also indicate if we want before and after hooks to be executed with a specific tag only. Example − @Before(‘@Web’). The same concept of tag logical and/or can be applied with hooks as well. Example − @Before(@dev,@wip), @Before(@dev,~@wip)