Saturday, 21 April 2018

cucumber: Hello World Application in command line mode

In this post, I am going to show you how to parse the .feature file using cucumber.

Step 1: Create a directory ‘jars’.

Step 2: Download below jars and keep them in ‘jars’ directory created in step 1.

1.   cucumber-core
2.   cucumber-java
3.   cucumber-jvm-deps
4.   gherkin

At the time of writing the article, I am using below maven dependencies.
<dependencies>
 <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-core -->
 <dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-core</artifactId>
  <version>2.3.1</version>
 </dependency>


 <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
 <dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-java</artifactId>
  <version>2.3.1</version>
 </dependency>

 <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm-deps -->
 <dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-jvm-deps</artifactId>
  <version>1.0.6</version>
  <scope>provided</scope>
 </dependency>

 <!-- https://mvnrepository.com/artifact/io.cucumber/gherkin -->
 <dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>gherkin</artifactId>
  <version>5.0.0</version>
 </dependency>
</dependencies>

Step 3: Go to the parent directory of ‘jars’ and run the command ‘java -cp "jars/*" cucumber.api.cli.Main -p pretty .’

C:\Users\krishna\Documents\Study\cucumber>java -cp "jars/*" cucumber.api.cli.Main -p pretty .
No features found at [.]

0 Scenarios
0 Steps
0m0.007s

As you see above snippet, Cucumber is unable to find the ‘.feature’ files in the current directory. Since there is no ‘.feature’ file, cucumber do not find any scenarios to execute.

‘-p pretty’ tell the cucumber, use pretty plugin while printing the output to console.

Step 4: let’s create ‘Login.feature’ file with below content.

Login.feature

Feature: Login

 Login should be quick and friendly.
 
 Scenario: Successful Login
  Users should be logged in successfully by providing correct username and password.
  
  Given I have chosen to Login
  When I log in with correct "username" and "password"
  Then I should be logged in successfully
  And I should see a personalized greeting message

My folder structure looks like below.

C:\Users\krishna\Documents\Study\cucumber>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 1034-4F6F

 Directory of C:\Users\krishna\Documents\Study\cucumber

01/25/2018  10:48 AM    <DIR>          .
01/25/2018  10:48 AM    <DIR>          ..
01/25/2018  09:54 AM    <DIR>          jars
01/25/2018  10:04 AM               359 Login.feature


Run the command ‘java -cp "jars/*" cucumber.api.cli.Main -p pretty .’. You can able to see below output.


C:\Users\krishna\Documents\Study\cucumber>java -cp "jars/*" cucumber.api.cli.Main -p pretty .
Feature: Login
        Login should be quick and friendly.

  Scenario: Successful Login[90m# ./Login.feature:5[0m
  Users should be logged in successfully by providing correct username and password.
  
  Given I have chosen to Login
  When I log in with correct "username" and "password"
  Then I should be logged in successfully
  And I should see a personalized greeting message

1 Scenarios ([33m1 undefined[0m)
4 Steps ([33m4 undefined[0m)
0m0.016s


You can implement missing steps with the snippets below:

@Given("^I have chosen to Login$")
public void i_have_chosen_to_Login() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@When("^I log in with correct \"([^\"]*)\" and \"([^\"]*)\"$")
public void i_log_in_with_correct_and(String arg1, String arg2) throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should be logged in successfully$")
public void i_should_be_logged_in_successfully() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should see a personalized greeting message$")
public void i_should_see_a_personalized_greeting_message() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

When you run the command, you can observe lot of output like above.
When you closely observe the output, you can see below things.
a.   Cucumber identifies the feature Login
b.   Cucumber identified one scenario, but do not know how to run it
c.   Cucumber printed below 4 method definition in java, where each step of the scenario ‘Successful Login’ mapped to one function.
@Given("^I have chosen to Login$")
public void i_have_chosen_to_Login() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@When("^I log in with correct \"([^\"]*)\" and \"([^\"]*)\"$")
public void i_log_in_with_correct_and(String arg1, String arg2) throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should be logged in successfully$")
public void i_should_be_logged_in_successfully() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should see a personalized greeting message$")
public void i_should_see_a_personalized_greeting_message() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

As you see the name of the functions, they are not following java naming convention (camel case).

By providing the option '--snippets camelcase', you can ask cucumber to generate the method names in camelcase.

java -cp "jars/*" cucumber.api.cli.Main -p pretty --snippets camelcase .


When I ran above command, I seen below method signatures.

@Given("^I have chosen to Login$")
public void iHaveChosenToLogin() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@When("^I log in with correct \"([^\"]*)\" and \"([^\"]*)\"$")
public void iLogInWithCorrectAnd(String arg1, String arg2) throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should be logged in successfully$")
public void iShouldBeLoggedInSuccessfully() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

@Then("^I should see a personalized greeting message$")
public void iShouldSeeAPersonalizedGreetingMessage() throws Exception {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

Step 5: It is time to create a java file, with the above generated code snippet.

Create a folder ‘cucumber_test’ and keep the LoginTest.java file there.


LoginTest.java

package cucumber_test;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class LoginTest {
 @Given("^I have chosen to Login$")
 public void iHaveChosenToLogin() throws Exception {
  // Write code here that turns the phrase above into concrete actions
  throw new PendingException();
 }

 @When("^I log in with correct \"([^\"]*)\" and \"([^\"]*)\"$")
 public void iLogInWithCorrectAnd(String arg1, String arg2) throws Exception {
  // Write code here that turns the phrase above into concrete actions
  throw new PendingException();
 }

 @Then("^I should be logged in successfully$")
 public void iShouldBeLoggedInSuccessfully() throws Exception {
  // Write code here that turns the phrase above into concrete actions
  throw new PendingException();
 }

 @Then("^I should see a personalized greeting message$")
 public void iShouldSeeAPersonalizedGreetingMessage() throws Exception {
  // Write code here that turns the phrase above into concrete actions
  throw new PendingException();
 }
}


Compile LoginTest.java file
javac -cp "jars/*" cucumber_test/loginTest.java

Run the generated classes using cucumber
java -cp "jars/*;." cucumber.api.cli.Main -p pretty --snippets camelcase -g cucumber_test .

Above command executes the test file located in package ‘cucumber_test’. As you see the above command, I added current directory ‘.’ to the class path. If you are using linux machine use ‘:’ ("jars/*:.") to separate paths.


When you run above command, it generates below kind of output.

C:\Users\krishna\Documents\Study\cucumber>java -cp "jars/*;." cucumber.api.cli.Main -p pretty --snippets camelcase -g cucumber_test .
Feature: Login
        Login should be quick and friendly.

  Scenario: Successful Login                             # ./Login.feature:5
                Users should be logged in successfully by providing correct username and password.
    Given I have chosen to Login                         # LoginTest.iHaveChosenToLogin()
      cucumber.api.PendingException: TODO: implement me
        at cucumber_test.LoginTest.iHaveChosenToLogin(loginTest.java:11)
        at ?.I have chosen to Login(./Login.feature:8)

    When I log in with correct "1musername" and "1mpassword" # LoginTest.iLogInWithCorrectAnd(String,String)
    Then I should be logged in successfully              # LoginTest.iShouldBeLoggedInSuccessfully()
    And I should see a personalized greeting message     # LoginTest.iShouldSeeAPersonalizedGreetingMessage()

1 Scenarios (1 pending)
4 Steps (3 skipped, 1 pending)
0.135s

cucumber.api.PendingException: TODO: implement me
        at cucumber_test.LoginTest.iHaveChosenToLogin(loginTest.java:11)
        at ?.I have chosen to Login(./Login.feature:8)

As you observe the output, cucumber is throwing ‘PendingException’.
Let’s implement the methods in ‘LoginTest.java’ file.


LoginTest.java

package cucumber_test;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class LoginTest {
 private String userName;
 private String password;
 
 @Given("^I have chosen to Login$")
 public void iHaveChosenToLogin() throws Exception {
  System.out.println("Opening login page");
 }

 @When("^I log in with correct \"([^\"]*)\" and \"([^\"]*)\"$")
 public void iLogInWithCorrectAnd(String userName, String password) throws Exception {
  this.userName = userName;
  this.password = password;
  
  if("username".equals(userName) && "password".equals(password)){
   System.out.println("User logged in with valid credentials");
  }else{
   throw new Exception("Wrong Credentials");
  }
 }

 @Then("^I should be logged in successfully$")
 public void iShouldBeLoggedInSuccessfully() throws Exception {
  System.out.println("Logged in Successfully");
 }

 @Then("^I should see a personalized greeting message$")
 public void iShouldSeeAPersonalizedGreetingMessage() throws Exception {
  System.out.println("Welcome " + userName);
 }
}

When you ran above application, you can able to see Welcome message in console.

To give more meaningful to the scenario, I updated Login.feature like below.


Login.feature

Feature: Login

 Login should be quick and friendly.
 
 Scenario: Successful Login
  Users should be logged in successfully by providing correct username and password.
  
  Given I have chosen to Login
  When I log in with user name "krishna" and password "password123"
  Then I should be logged in successfully
  And I should see a personalized greeting message


LoginTest.java

package cucumber_test;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class LoginTest {
 private String userName;
 private String password;
 
 @Given("^I have chosen to Login$")
 public void iHaveChosenToLogin() throws Exception {
  System.out.println("Opening login page");
 }

 @When("^I log in with user name \"([^\"]*)\" and password \"([^\"]*)\"$")
 public void iLogInWithCorrectAnd(String userName, String password) throws Exception {
  this.userName = userName;
  this.password = password;
  
  if("krishna".equals(userName) && "password123".equals(password)){
   System.out.println("User logged in with valid credentials");
  }else{
   throw new Exception("Wrong Credentials. userName " + userName);
  }
 }

 @Then("^I should be logged in successfully$")
 public void iShouldBeLoggedInSuccessfully() throws Exception {
  System.out.println("Logged in Successfully");
 }

 @Then("^I should see a personalized greeting message$")
 public void iShouldSeeAPersonalizedGreetingMessage() throws Exception {
  System.out.println("Welcome " + userName);
 }
}

Compile LoginTest.java and run the program, you can able to see welcome message.

Compile LoginTest.java
javac -cp "jars/*" cucumber_test/loginTest.java

Run LoginTest class file
java -cp "jars/*;." cucumber.api.cli.Main -p pretty --snippets camelcase -g cucumber_test .


My directory structure looks like below.

C:\Users\krishna\Documents\Study\cucumber>dir
 Volume in drive C is OSDisk
 Volume Serial Number is 1034-4F6F

 Directory of C:\Users\krishna\Documents\Study\cucumber

01/25/2018  12:02 PM    <DIR>          .
01/25/2018  12:02 PM    <DIR>          ..
01/25/2018  09:54 AM    <DIR>          jars
01/25/2018  11:58 AM               372 Login.feature


Previous                                                 Next                                                 Home

No comments:

Post a Comment