Sunday, December 27, 2015

Hooks And Tags On Cucumber JVM

Hooks and Tags are most interesting topic on Cucucmber-JVM.

Hooks is a technique to run set of code before and after the whole Feature or Scenarios. So we need to use

@Before 
     and
@After

annotation for hook feature of Cucumber-JVM. We need to be sure when we use those above mentioned annotation then we should import below mentioned packages on Step generation or Glue Code file

import cucumber.api.java.After;
import cucumber.api.java.Before;


It is possible to define a hook so that it is only executed before or after scenarios that are tagged with a specified annotation

We will define this on Feature file and pass this tag value on @Before or @After method on step file. It should be looked like below:

@Before("@add")
        or
@Before(value={"@add"})
@After(value={"@add"}))

Feature file should be :

Feature: This is a sample feature file
@add
    Scenario: This is a scenario for Adding two number.
        Given Two number as 1 and 6
        When We add this two given number
        Then Sum Result should be 7 

 
We can use AND/OR logic on hooks also.

Syntax for AND logic is:
@Before(value={"@add","@sub"})
@After(value={"@add","@sub"})

Syntax for OR logic is :
@Before(value={"@add,@sub"})
@After(value={"@add,@sub"})

 So AND logic means hooks will be executed when all tags are matched with the feature file tags and OR logic means when any of the tag matched with feature file.

We can also mention the execution order when we will use multiple hooks. Syntax looks like below:

@Before(order=5) 
@After(order =5) 

If we use multiple @Before with different order then lower order number execute first but behavior of  @After method is opposite, upper order number execute first then execute the lower order number.

 Complete Code:

Feature File :

Feature: This is a sample feature file
 

@tag1
    Scenario: This is a scenario for Adding two number.
        Given Two number as 1 and 6
        When We add this two given number
        Then Sum Result should be 7
@tag2 @tag3   
    Scenario: This is a scenario for sub two number.
        Given Two number as 8 and 1
        When We substract this two given number
        Then Sub Result should be 7   
       
@tag4 @tag5
    Scenario: This is a scenario for sub two number.
        Given Two number as 6 and 1
        When We add this two given number
        Then Sum Result should be 7
        And We substract this two given number
        Then Sub Result should be 5   
  
 
 

Glue Code : 

import org.junit.Assert;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class SumFeatureTest {
    @Before(order=1,value={"@tag1"})
    public void beforeMethod(){
        System.out.println("This will be executed When Tag Matched With The Following Tag Matched :@tag1. ");
    }
    @Before(order=5,value={"@tag1"})
    public void beforeMethodForOrderSingle(){
        System.out.println("Upper Order Value Execute Later For @Before Method. This Is Executed From Single Tag Method : beforeMethodForOrderSingle ");
    }

    @Before(order=1,value={"@tag4","@tag5",})
    public void beforeMethodAND(){
        System.out.println("This will be executed When Both Of The Following Tag Matched :@tag4 AND @tag5. ");
    }
    @Before(order=5,value={"@tag4","@tag5"})
    public void beforeMethodForOrderAND(){
        System.out.println("Upper Order Value Execute Later For @Before Method. This Is Executed From AND Tag Method : beforeMethodForOrderAND ");
    }
    @Before(order=1,value={"@tag2,@tag3"})
    public void beforeMethodOR(){
        System.out.println("This will be executed When Any Of The Following Tag Matched : @tag2 OR @tag3. ");
    }
    @Before(order=5,value={"@tag2,@tag3"})
    public void beforeMethodforOrderOR(){
        System.out.println("Upper Order Value Execute Later For @Before Method.This Is Executed From OR Tag Method : beforeMethodforOrderOR ");
    }
    @After(order=1)
    public void afterMethod(){
        System.out.println("Lower Order Value Execute Later For @After Method.");
    }
    @After(order =5)
    public void afterMethod1(){
        System.out.println("Upper Order Value Execute First For @After Method.");
    }
    int input1,input2,sumResult,subResult;
    @Given("^Two number as (\\d+) and (\\d+)$")
    public void twoNumberGivenAsAndAnotherIs(int firstInput, int secondInput) throws Throwable {
        input1 = firstInput;
        input2 = secondInput;
    }

    @When("^We add this two given number$")
    public void weAddThisTwoGivenNumber() throws Throwable {
        sumResult = input1+input2;
        System.out.println("sum");
    }
    @When("^We substract this two given number$")
    public void weSubstractThisTwoGivenNumber() throws Throwable {
        subResult = input1-input2;
        System.out.println("sub");
    }
    @Then("^Sum Result should be (\\d+)$")
    public void sumResultShouldBe(int expectedTotal) throws Throwable {
        Assert.assertEquals("Not Matched: ", expectedTotal, sumResult);
    }
    @Then("^Sub Result should be (\\d+)$")
    public void subResultShouldBe(int expectedTotal) throws Throwable {
        Assert.assertEquals("Not Matched: ", expectedTotal, subResult);
    }
   


Runner Class:

import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.SnippetType;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(
        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
                "progress:target/cucumber-progress.txt"
        },features ={"./sample.feature"},
            glue ={"com/automation/steps"},
            monochrome = true, snippets= SnippetType.CAMELCASE)
public class Runner {
} 

Tuesday, December 22, 2015

Different Option On Cucumber JUnit Runner

We can use different option of Cucumber-JVM JUnit runner using @CucumberOption annotation.

There are so many option available with @CucumberOption annotation.We will discuss in details below :

features : This is the most important part of the cucumber option.It is used to mention the path of the feature files like features ={"./sample.feature"} or mention the only folder of feature file, cucumber automatically get all the feature file in the mentioned path.

glue : This is the another most important part of the cucumber option.It is used to mention the path of the glue code files like glue ={"com/automation/steps"}. Cucumber automatically get all the glue codecorrespondng to the feature file.

snippets : This is used when we try to generate basic code structure with the different syntax style(like camelcase or underscore) from the feature file. We use this option in JUnit runner and run this file, after running this we get the basic method structure for the particular feature file on console of the editor. Syntax looks like this : snippets= SnippetType.CAMELCASE
 

monochrome : It is used to get the better result on console of the editor. Syntax is monochrome = true
 

plugin : It is another most important part of the Cucumber JVM runner option. It is used to generate different type of reporting style. We get html report json report xml report and many more type of report. Syntax is describe below:

        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
                "progress:target/cucumber-progress.txt"
        }


dryRun : It is used to verify that all steps of the feature file defined on step generator or glue code file or not. Syntax is : dryRun= true
One thing keep in mind that when dryRun=true then entire code should not run only it checks that all the methods matched with feature file or not.  

strict: It is used to verify that all steps of the feature file defined on step generator or glue code file or not.
Syntax is : strict= true
Difference between dryRun and strict is that strict run allow execute the code and report as fail if any steps not implemented on feature code.

tags : It is a another option on Cucumber-JVM JUnit runner by which we can execute mentioned tags Syntax is : tags={"@tag1}.This tag should be mentioned on feature file like 
Feature: This is a sample feature file
@tag1
    Scenario: This is a scenario for Adding two number.
        Given Two number as 1 and 6
        When We add this two given number
        Then Sum Result should be 7


 We will discuss details on later post about this.

So after implement all the details runner class @CucumberOption should be looked like this :

@CucumberOptions(
        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
                "progress:target/cucumber-progress.txt"
        },features ={"./sample.feature"},
            glue ={"com/automation/steps"},strict = true,
            dryRun= false,monochrome = true, snippets= SnippetType.CAMELCASE,tags={"@tag1"})

Sunday, December 20, 2015

Start Coding With Cucumber JVM

Now we know the basic terms and different component of cucumber. Here we will create a simple program using cucumber-jvm. We will follow the below steps to create a simple projects using cucumber-jvm.

So cucumber-jvm must have three parts
  1. Code Runner Class
  2. Feature File
  3. Glue Code Or Step Generation File.

Step 1:

@RunWith   annotation:

 We need help from JUnit to run cucumber tests. So we need to use @RunWith annotation to call the cucumber class from normal JUnit class and pass Cucumber.class as a parameter in @RunWith annotation and put this annotation above the class name means before the class declaration starts.

So after using this annotation in JUnit class it should look like below :

@RunWith(Cucumber.class)
public class Runner {
}


@CucumberOptions:

features and glue option :

 If we think logically then we can understand that we also need to send the feature file location and glue code or step generation file location. It can be possible using @CucumberOptions annotation and passing feature file location using features={"./newtest.feature"} and passing glue code or step generation file location or package name using
glue ={"com/automation/steps"}.

We can pass multiple features or step generation file in the same project then we pass the multiple file separated by comma then features option should be looks like below 
 features={"./newtest.feature","./newtest1.feature"}

and glue should be looks like:  
 glue ={"com/automation/steps","com/automation/anothersteps"}

So in summary @CucumberOptions should be looks like below
@CucumberOptions( features={"./newtest.feature"},glue ={"com/automation/steps"})

plugin option:

plugin option is used for creating different type of  reporting. Different types of  reports created under the target folder so syntax for creating different type of report is describe below :
        Syntax for html report is                :plugin = {"html:target/cucumber-html-report"}
       
Syntax for json report is                 :plugin = {"json:target/cucumber.json"}         
        Syntax for text report is                  :plugin = {"pretty:target/cucumber-pretty.txt"}
       
Syntax for json usage report is       :plugin = {"usage:target/cucumber-usage.json"}
       
Syntax for xml report is                  :plugin = {"junit:target/cucumber-results.xml"}
Here we also mention the different type of reports format with comma separated option. So @CucumberOption should be looks like below with different type of  reporting option.

@CucumberOptions(
        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
        })


So at last our runner class should be looks like below:


import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.SnippetType;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(
        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
        },features={"./newtest.feature"},
            glue ="com/automation/steps",
            dryRun=false,monochrome = true, snippets= SnippetType.CAMELCASE)

public class Runner {
}


Step 2:


Now we create a .feature file for a sample. Here we create a scenario where we add two number as 1 and 6 and result should be 7. So our feature file looks like below:

Feature: This is a sample feature file

    Scenario: This is a scenario for Adding two number.
        Given Two number as 1 and 6
        When We add this two given number
        Then Result should be 7

 

Step 3:


 So we are now creating our glue or step definition file for this particular step file. Glue code or step definition file is nothing but a java file. Step definition file should be looks like below :

public class Test {
    int input1,input2,total;
    @Given("^Two number as (\\d+) and (\\d+)$")
    public void twoNumberGivenAsAndAnotherIs(int firstInput, int secondInput) throws Throwable {
        input1 = firstInput;
        input2 = secondInput;
    }

    @When("^We add this two given number$")
    public void weAddThisTwoGivenNumber() throws Throwable {
        total = input1+input2;
    }

    @Then("^Result should be (\\d+)$")
    public void resultShouldBe(int expectedTotal) throws Throwable {
        Assert.assertEquals("Not Matched: ", expectedTotal, total);
    }

}

 Regular expression is used on each annotation so we are now try to understand the meaning of the below regular expression:
^  =  This is used to mentioned that string is starting from here.
$  =  This is used to mentioned that string ends here.
+  =  This is used to find one or more time.
\d =  This is used to represent digit.
\   =  This expression represent the escape characters.

So now question is how we will create the basic structure of glue or step definition file? 

It is very easy we just run the cucumber Runner class after creating the feature file then we observe that something written over the console pane of the eclipse it should be looks like below :

You can implement missing steps with the snippets below:

@Given("^Two number as (\\d+) and (\\d+)$")
public void twoNumberAsAnd(int arg1, int arg2) throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@When("^We add this two given number$")
public void weAddThisTwoGivenNumber() throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^Result should be (\\d+)$")
public void resultShouldBe(int arg1) throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}


 Now we remove the comments and PendingException() and implement our logic.

[Note: If we observe deeply then we can understand the method name of auto generated code follow the camel notation because we mention snippets= SnippetType.CAMELCASE on @CucumberOptions annotation on cucumber runner class. Default it follow the underscore notaion for method name]

So our complete code looks like below:

Runner Class :

 

import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.SnippetType;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)

@CucumberOptions(
        plugin = {
                "html:target/cucumber-html-report",
                "json:target/cucumber.json",
                "pretty:target/cucumber-pretty.txt",
                "usage:target/cucumber-usage.json",
                "junit:target/cucumber-results.xml",
        },features ={"./sample.feature"},
           glue ={"com/automation/steps"},snippets= SnippetType.CAMELCASE)

public class Runner {
}

 

Feature File :

 

Feature: This is a sample feature file

    Scenario: This is a scenario for Adding two number.
        Given Two number as 1 and 6
        When We add this two given number
        Then Result should be 7  

 

Glue Code Or Step Definition File:

 

import org.junit.Assert;
import cucumber.api.DataTable;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class SumFeatureTest {

    int input1,input2,total;
    @Given("^Two number as (\\d+) and (\\d+)$")
    public void twoNumberGivenAsAndAnotherIs(int firstInput, int secondInput) throws Throwable {
        input1 = firstInput;
        input2 = secondInput;
    }

    @When("^We add this two given number$")
    public void weAddThisTwoGivenNumber() throws Throwable {
        total = input1+input2;
    }

    @Then("^Result should be (\\d+)$")
    public void resultShouldBe(int expectedTotal) throws Throwable {
        Assert.assertEquals("Not Matched: ", expectedTotal, total);
    }
}