Developing your web-app the  Behavior Driven Development way using Cucumber, Gherkin and Selenium.

Developing your web-app the Behavior Driven Development way using Cucumber, Gherkin and Selenium.

Okay I promise I am not talking about a recipe here, hence the word Cucumber, if you want kitchen advice then you should most probably ask your mom, and I am not here to scare you, because to me the sound of Gherkin is a bit scary, I am here to talk about developing your web-app, the Behavior Driven Development way.

In this article what I will talk about is:

  • Slightly about TDD (Test Driven Development)
  • BDD ( Behavior Driven Development )
  • Finally using Cucumber and Selenium to automate your BDD

Before we start, lets first clear this misconception and agree on that, Test Driven Development / Behavior Driven Development are NOT testing. It involves writing test cases yes, but its mainly a development approach, you write your test cases, they fail and you DRIVE your development from them.

TDD:


Test Driven Development is basically 3 steps:

  1. writing failing tests (writing the next specification)
  2. make your tests pass quickly
  3. refactor

repeat... repeat...

So First, you start by writing the failing tests, and the intent here is not to write a 'failing' test but to write the next specification and what value you expect, that will also help you think about edge cases that you might not think of if you start by the developing first, and finally it sort of enforces writing test cases for coverage.

Second, you write your code and you make it pass and all green, the intent here is to make it pass and not to have the best possible code. Make it pass quickly.

Finally after it passes, you refactor your code, see what design can be better, what piece of code you can write in a cleaner way, and since you have tests written, you can refactor until you are happy, not only that but make sure that your tests passes and they are still green.

BDD:

Behavior Driven Development s a bit more sophisticated, some might say its the same like TDD some say its not, lets care less about that but first understand what is it. As we agreed earlier, its a development approach, its similar to TDD in the sense that your write your tests first, make it pass and then refactor, however it differs from TDD in the sense that, the tests are more user focused, and more behavior wise, your tests cases are written in a common languages that, the developers, testers and the business people who came with the requirements understand. That still sounds vague so lets have an example:

Our Books Web App example:

Lets say that you have a very simple books web app where the user would login, find a list of books in the page and once he clicks on one of the books, it will take him to the Amazon page that sells that book, as simple as that.

In order to develop this web app, developers, and testers and the business people sit together tries to come up with the specification, in a language that every one understands, it imitates a concrete behavior that how the end user will use the app and from there it will drive the development, to see what I am talking about here is an example:

Feature: Exploring books and choosing a book to buy
the user will login, explore the different books available and when he chooses 
a book, he will be redirected to the Amazon webpage of that book to buy it

Scenario: buying a book through the books webapp

Given I am a user with a username test_user and password test_123
When I login to the books app 
And I click on the book Men Are from Mars, Women Are from Venus
Then I expect to be taken to the Amazon page of the book Women From Mars and Men From Venus

This is your test case, this is a real test case for a feature even though you feel like its just a pure English and there is no code here,but that is the beauty about it,its more user focused, and its in a language that even the business people can understand, its concrete, it shows and tests specific feature, this app here is small, it has one feature now and one scenario, but ideally, in your app you will be having different features, in every feature you might have more than one scenario.

The main idea here about BDD, it starts with the collaboration between everybody involved, the scenarios (developers, testers, business people ) and features get recorded in a common language and finally its automated.

  1. Collaborate
  2. Record
  3. Automate

The main thing to notice about BDD and TDD is that, they both start from outside, thinking about are we all trying to achieve,and use examples to make sure that everybody on the team understands and then move to the inside by implementing it.

Your cucumber features should drive your implementation, not reflect it.

now after we understand TDD, and BDD we can talk about Cucumber, Gherkin and Selenium, I will get a bit technical so we can understand

Cucumber:

So now you know BDD, Cucumber is a tool that supports Behavior Driven Development, Behavior Driven Development is the Development approach, and Cucumber is the tool.

What Cucumber does is that, it reads executable specifications written in plain text and validates that the software does what those specifications say.

Cucumber looks in a specific folder for all feature files, that contain the executable steps, executable steps for example can be some steps that define login to the web app, that is an executable step. So when cucumber finds this executable step in the feature file which is written in pure English(or any other language) , it maps this with a step definition written in your Programming language of choice that performs the actual test, so for example this is my executable specification in the feature file: buy_books.feature

Given I am a user with a username test_user and password test_123

So now , this executable specification will drive my implementation and I will start developing my app, so I go write my code -> test -> make it pass -> refactor.

lets say I am done with this feature and its time to make it pass:

Cucumber maps this executable specification written in pure English to a step definition written in your favorite programming languages, for example in Java you will define the step as follows (assuming that I have implemented my business logic and the User Class):

In a file called BuyBookSteps.java

// Some code before this ....

@Given("^I am a user with a username (.+) and password (.+)$", (String username, 
String password) -> 
{
User testUser = new User();
testUser.setUsername(username);
testUser.setPassword(password);
});

//Some other code bellow...
});

so what happened here is:

  • you have your feature file written through collaboration by everyone, in English
  • when you run Cucumber, it looks for all .feature files :here buy_books.feature
  • so it reads the the feature file, find the executable steps, maps these steps to BuyBookSteps.java based on their regular expression matching, lets take this as an example, in the feature file buy_books.feature
Given I am a user with a username test_user and password test_123

matches the following from BuyBookSteps.java file :

@Given("^I am a user with a username (.+) and password (.+)$", (String username, String password) -> 

if you notice, the two definitions are almost the same, however they are different in the passed parameters :

  • So basically the first (.+) in BuyBookSteps.java matches the username test_user in buy_books.feature and maps it to a String called username passed to the test function (lambda expression in this case)
  • The second (.+) in BuyBookSteps.java matches the password test_123 in buy_books.feature and maps it to a String called password and passed to the test function (lambda expression in this case)

This is more like: please from the feature file, match these parameters and pass them to my test function in the BuyBookSteps.java file !

Its really important to understand regular expressions, not all of it but just enough for cucumber

So as you see here your plain English test specification, matches an actual programming steps and allows use to pass parameters through regular expressions easily from your .feature file to your Steps.Java file, how powerful!

Gherkin syntax:

Don't worry! its not something new, so BDD is BDD! Cucumber is the tool that supports BDD, and Gerkhin is the syntax used previously in our .feature file

lets go back to our very simple book web-app above and try to understand what Cucumber does:

Feature: Exploring books and choosing a book to buy
the user will login, explore the different books available and when he chooses 
a book, he will be redirected to the Amazon webpage of that book to buy it

Scenario: buying a book through the books webapp

Given I am a user with a username test_user and password test_123
When I login to the books app 
And I click on the book Men Are from Mars, Women Are from Venus
Then I expect to be taken to the Amazon page of the book Women From Mars and Men From Venusm Venus

There are a few keywords in this feature file lets briefly talk about them:

Feature: provide a high-level description of a software feature, and to group related scenarios. in this case we have only one scenario, but you might have a case where a few scenarios can be grouped together under one feature. The Feature keyword is NOT executable, so that cucumber doesn't execute anything when it sees the Feature keyword

Scenario: the Scenario or the example that represents the business case

Given, When, Then Step definitions(executable) :

  • Given steps:Describe an initial context, this is where you define your initial state of the system
  • When steps:Describe an event, for example When the user logs in, or When the user logs out .. etc
  • Then Steps:Describe an expected outcome, this is where you verify the expected out come

Now we know TDD, BDD, Cucumber and Gherkin, only one left:

Selenium: there is no better description for Selenium than the one available in their official websites:

Selenium automates browsers

As simple as that, but lets explain it a bit more if you are still in doubt!

so basically lets say you are trying to test the web app we talked about what do you Manually do:

  • open the web page
  • enter your username-> enter your password -> click login
  • click on a book
  • finally see the book in the Amazon website

This now seems easy and simple and you can do it manually, but imagine if you have tens of features, and tens of scenarios, doing it manually is not feasible, so Selenium Automate that for you!

you want to open a webpage, Selenium will do that:

driver.get("https://www.myawsomeapp.com");

you want to find an element present in the page?

<table id="myAwsomeTable">...</table>

Selenium will do that for you:

WebElement element = driver.findElement(By.id("myAwsomeTable"));

you want to fill a the username field ?

WebElement element = driver.findElement(By.id("username"));
element.sendKeys("test_user");

Its neat, it automates your browser and can simply be integrated with your Cucumber to make a robust BDD for web apps:

lets apply it in our application:

In the buy_books.feature file I have this executable step:

When I login to the books app

Now, I want to write the step definition for this, remember where should we write it ?

The BuyBookSteps.java

@And ("^I login to to the books app $", () -> 
{
// this will fill the username and password textbox
WebElement usernamEelement = driver.findElement(By.id("username"));

usernamEelement .sendKeys(testUser.username);

WebElement passwordEelement = driver.findElement(By.id("password"));

passwordEelement.sendKeys(testUser.password);


// this will click on the submit button, Automatically!
driver.findElement(By.id("submit")).click();


});

as you can see how powerful this combination is, you write in Gherkin syntax, Cucumber features, and you write the corresponding Steps where you use Selenium to automate the browser for you.

Extra:

Why is Cucumber named as such: Long story short, the inventor of Cucumber, when he first started developing the tool, he committed his first code with the name stories because he didn't have a better name. He then asked his wife for and asked her to suggest a catchy - non geeky name, she paused for a while, and said Cucumber!

Regular expressions is really important, and I can't count the times where I had to write regular expressions, but every now and then they slip! and you need to recheck them, I have been using the same reference for more than 5 years, its the best I found.You can also check the quick guide for Cucumber from here.


Alfred S.

Engineering Chapter Lead

6 年

Hor Jin Foong Sabir Moglad salad is served!

Momen Tageldeen

Senior Engineer @ AMD | ASIC for AI

6 年

A great article as usual. I always find myself looking forward to your posts. Short, sweet and extremely informative.

回复

要查看或添加评论,请登录

Sabir Moglad的更多文章

社区洞察

其他会员也浏览了