Behavior-Driven Development (BDD) is a methodology that bridges the gap between business and technical teams by emphasizing collaboration. It uses plain language to define application behavior, making it easier for non-technical stakeholders to contribute to the development process. Selenium and Cucumber are widely used together in BDD to automate web application testing.
This blog provides a detailed guide to implementing BDD using Selenium and Cucumber, including coding examples to help you get started.
What is BDD?
BDD focuses on the behavior of an application from the end user’s perspective. It uses scenarios written in Gherkin, a domain-specific language with a simple syntax:
-
Given: Precondition or context.
-
When: Action or event.
-
Then: Outcome or result.
Example:
<div><pre><span>Feature:</span><span> Login Functionality</span> <span> </span><span>Scenario:</span><span> Valid user logs in successfully</span> <span> Given </span><span>the user is on the login page</span> <span> </span><span>When </span><span>the user enters valid credentials</span> <span> </span><span>Then </span><span>the user is redirected to the dashboard</span></pre> </div> <p></p>
Tools Used
Selenium: Automates web browsers to test web applications.
Cucumber: Enables writing tests in plain English (Gherkin syntax).
Java: Programming language for writing test automation scripts.
JUnit/TestNG: Test framework to execute Cucumber tests.
Setting Up Your Project
Create a Maven Project:
Add dependencies in
pom.xml
:
<div><pre><span><dependencies></span> <span><dependency></span> <span><groupId></span>io.cucumber<span></groupId></span> <span><artifactId></span>cucumber-java<span></artifactId></span> <span><version></span>7.11.0<span></version></span> <span></dependency></span> <span><dependency></span> <span><groupId></span>io.cucumber<span></groupId></span> <span><artifactId></span>cucumber-junit<span></artifactId></span> <span><version></span>7.11.0<span></version></span> <span></dependency></span> <span><dependency></span> <span><groupId></span>org.seleniumhq.selenium<span></groupId></span> <span><artifactId></span>selenium-java<span></artifactId></span> <span><version></span>4.10.0<span></version></span> <span></dependency></span> <span></dependencies></span></pre> </div> <p></p>
Directory Structure:
src/test/java
: For step definitions.
src/test/resources
: For feature files.
Writing a Feature File
Save this file as
login.feature
insrc/test/resources/features
:
<div><pre><span>Feature:</span><span> Login Functionality</span> <span> </span><span>Scenario:</span><span> Valid user logs in successfully</span> <span> Given </span><span>the user is on the login page</span> <span> </span><span>When </span><span>the user enters valid credentials</span> <span> </span><span>Then </span><span>the user is redirected to the dashboard</span> <span> </span><span>Scenario:</span><span> Invalid user cannot log in</span> <span> Given </span><span>the user is on the login page</span> <span> </span><span>When </span><span>the user enters invalid credentials</span> <span> </span><span>Then </span><span>an error message is displayed</span></pre> </div> <p></p>
Creating Step Definitions
Create a Java file
LoginSteps.java
insrc/test/java/stepdefinitions
:
<div><pre><span>package</span> stepdefinitions; <span>import</span> <span>org.openqa.selenium.By</span>; <span>import</span> <span>org.openqa.selenium.WebDriver</span>; <span>import</span> <span>org.openqa.selenium.WebElement</span>; <span>import</span> <span>org.openqa.selenium.chrome.ChromeDriver</span>; <span>import</span> <span>io.cucumber.java.en.*</span>; <span>public</span> <span>class</span> <span>LoginSteps</span> { WebDriver driver; <span>@Given</span>(<span>"the user is on the login page"</span>) <span>public</span> <span>void</span> <span>userIsOnLoginPage</span>() { System.<span>setProperty</span>(<span>"webdriver.chrome.driver"</span>, <span>"path_to_chromedriver"</span>); driver = <span>new</span> ChromeDriver(); driver.<span>get</span>(<span>"https://example.com/login"</span>); } <span>@When</span>(<span>"the user enters valid credentials"</span>) <span>public</span> <span>void</span> <span>userEntersValidCredentials</span>() { WebElement username = driver.<span>findElement</span>(By.<span>id</span>(<span>"username"</span>)); WebElement password = driver.<span>findElement</span>(By.<span>id</span>(<span>"password"</span>)); WebElement loginButton = driver.<span>findElement</span>(By.<span>id</span>(<span>"login"</span>)); username.<span>sendKeys</span>(<span>"validUser"</span>); password.<span>sendKeys</span>(<span>"validPassword"</span>); loginButton.<span>click</span>(); } <span>@Then</span>(<span>"the user is redirected to the dashboard"</span>) <span>public</span> <span>void</span> <span>userIsRedirectedToDashboard</span>() { String expectedUrl = <span>"https://example.com/dashboard"</span>; <span>assert</span> driver.<span>getCurrentUrl</span>().<span>equals</span>(expectedUrl); driver.<span>quit</span>(); } <span>@When</span>(<span>"the user enters invalid credentials"</span>) <span>public</span> <span>void</span> <span>userEntersInvalidCredentials</span>() { WebElement username = driver.<span>findElement</span>(By.<span>id</span>(<span>"username"</span>)); WebElement password = driver.<span>findElement</span>(By.<span>id</span>(<span>"password"</span>)); WebElement loginButton = driver.<span>findElement</span>(By.<span>id</span>(<span>"login"</span>)); username.<span>sendKeys</span>(<span>"invalidUser"</span>); password.<span>sendKeys</span>(<span>"invalidPassword"</span>); loginButton.<span>click</span>(); } <span>@Then</span>(<span>"an error message is displayed"</span>) <span>public</span> <span>void</span> <span>errorMessageIsDisplayed</span>() { WebElement error = driver.<span>findElement</span>(By.<span>id</span>(<span>"error"</span>)); <span>assert</span> error.<span>isDisplayed</span>(); driver.<span>quit</span>(); } }</pre> </div> <p></p>
Configuring the Runner Class
Create a Java file
TestRunner.java
insrc/test/java/runners
:
<div><pre><span>package</span> runners; <span>import</span> <span>org.junit.runner.RunWith</span>; <span>import</span> <span>io.cucumber.junit.Cucumber</span>; <span>import</span> <span>io.cucumber.junit.CucumberOptions</span>; <span>@RunWith</span>(Cucumber.<span>class</span>) <span>@CucumberOptions</span>( features = <span>"src/test/resources/features"</span>, glue = <span>"stepdefinitions"</span>, plugin = {<span>"pretty"</span>, <span>"html:target/cucumber-reports"</span>}, monochrome = <span>true</span> ) <span>public</span> <span>class</span> <span>TestRunner</span> { }</pre> </div> <p></p>
Running Your Tests
Open a terminal.
Navigate to your project directory.
Run the following command:
<div><pre><span>mvn test</span></pre> </div> <p></p>
This will execute all scenarios defined in the
login.feature
file.
Best Practices for BDD with Selenium and Cucumber
Keep Scenarios Simple: Use concise and descriptive steps in Gherkin.
Reuse Step Definitions: Avoid duplicating code by reusing steps where possible.
Parameterize Steps: Handle multiple inputs by parameterizing your Gherkin steps.
Organize Files: Maintain a clear structure for features, steps, and configurations.
Continuous Integration: Integrate Cucumber tests with CI/CD pipelines for automated execution.
Conclusion
BDD with Selenium and Cucumber is a powerful combination for creating readable, maintainable, and effective test automation suites. By leveraging this approach, teams can foster collaboration, improve test coverage, and ensure high-quality software delivery. Start implementing BDD in your projects today and experience its benefits firsthand!
Keywords: BDD, Selenium, Cucumber, Automation Testing, Behavior-Driven Development, Gherkin, Step Definitions, Test Automation Framework.
Source: Read More