Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

I have a normal Springframework-enabled project arranged as a Maven project. There were already JUnit tests in the project, along with the requisite Spring configuration.

I needed to add Cucumber tests to the project. I started by adding a cucumber directory to my src/test/java and src/test/resources directories.

I added my feature file in ../src/test/resources/com/cdi/igs/adapter/cucumber/features/Login.feature.

Feature: Login

  @2014w34 @US2422
  Scenario Outline: A lite registered player with email verified should be able submit username and password in the poker client.
  After submission player will see a system message to complete registration and will get re-direct to complete registration step 2 in IGP

    Given my username is "<UserName>"
    And my password is "<Password>"
    And my registration status is "lit"
    And my email verification status is verified as "<email verification status>"
    When I provide my credentials
    Then I should receive the following Poker status "<login result>"
  Examples:
    | UserName | Password   | login result            |email verification status|
    | player1  | Password#1 | AUTH_FAILED_LIT         | 1                       |
  @2014w34 @US2326
  Scenario Outline: A fully registered user should be able to login into the existing poker client. User in examples must be a fully registered user. 0 = SUCCESS, 1 = AUTH_FAILED

    Given my username is "<UserName>"
    And my password is "<Password>"
    And my registration status is "ful"
    When I provide my credentials
    Then I should receive the following Poker status "<Login Result>"
    And I should receive the following demographic data "<First Name>" "<Last Name>" "<Address1>" "<Address2>" "<City>" "<State>" "<Zip>"
    And I should have a third party authentication token

  Examples:
    | UserName | Password   | Login Result | First Name | Last Name | Address1          | Address2 | City     | State | Zip   |
    | player2  | Password#1 | SUCCESS      | Player     | Test      | 1505 Test Address | Apt 100  | New York | NY    | 80000 |


  @2014w34 @US2538
  Scenario Outline: A lite registered user  whose email is not verified will be shown the relevant messaging, and they will be requested to become fully registered
    Given my username is "<UserName>"
    And my password is "<Password>"
    And my registration status is "lit"
    And my email verification status is verified as "<email verification status>"
    When I provide my credentials
    Then I should receive the following Poker status "<login result>"

  Examples:
    | UserName    | Password        |email verification status  | login result             |
    | 8player     | Password!#01    |0                          | AUTH_FAILED_LIT_NO_EMAIL |


  @2014w36 @US2639
  Scenario Outline: Player with existing Password locked status with IGP authentication, cannot login to poker client.

    Given my username is "<UserName>"
    And my password is "<Password>"
    And my person status is "psl"
    When I provide my credentials
    Then I should receive the following Poker status "<login result>"

  Examples:
    | UserName | Password     | login result              |
    | gawky1  | Password#1    | LOCKED_PASSWORD_RESET     |

  @2014w36 @US2629
  Scenario Outline: Player with existing Reset locked status with IGP authentication, cannot login to poker client.

    Given my username is "<UserName>"
    And my password is "<Password>"
    And my person status is "rsl"
    When I provide my credentials
    Then I should receive the following Poker status "<login result>"

  Examples:
    | UserName  | Password      | login result                  |
    | gawky     | Password#1    | LOCKED_CUSTOMER_SERVICE_RESET |

I added my steps file that defines the implementations in …/src/test/java/com/cdi/igs/adapter/cucumber/steps/LoginSteps.java.

package com.cdi.igs.adapter.cucumber.steps;

import com.cdi.igs.adapter.login.LoginRequest;
import com.cdi.igs.adapter.login.LoginResponse;
import com.cdi.igs.adapter.poker.login.PokerLoginService;
import com.cdi.igs.dao.person.Person;
import com.cdi.igs.dao.person.PersonRepository;
import com.cdi.igs.dao.personhasverifiableitem.PersonHasVerifiableItem;
import com.cdi.igs.dao.personhasverifiableitem.PersonHasVerifiableItemRepository;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;

import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
 * Login cucumber steps.
 * @author norris.shelton
 */
@ContextConfiguration("classpath:TestCucumber-context.xml")
public class LoginSteps {
    @Autowired
    private PersonRepository        personRepository;
    @Autowired
    private PersonHasVerifiableItemRepository personHasVerifiableItemRepository;
    @Autowired
    private PokerLoginService       pokerLoginService;


    private String     username;
    private String     password;
    private Person     person;
    LoginResponse loginResponse;

    @Given("^my username is "([^"]*)"$")
    public void my_username_is(String username) throws Throwable {
        this.username = username;
    }


    @And("^my password is "([^"]*)"$")
    public void my_password_is(String password) throws Throwable {
        this.password = password;
    }

    @Given("^my registration status is "(.*?)"$")
    public void my_registration_status_is(String registrationStatus) throws Throwable {
        person = personRepository.findByUserName(username);
        assertEquals(registrationStatus, person.getIdRegistrationStatus());
    }



    @Then("^I should receive the following Poker status "(.*?)"$")
    public void i_should_receive_the_following_Poker_status(String responseStatus) throws Throwable {
        assertEquals(responseStatus, loginResponse.getStatus().value());
    }

    @Given("^my email verification status is verified as "(.*?)"$")
    public void my_email_verification_status_is_verified_as(String emailVerificationStatus) throws Throwable {
     List<PersonHasVerifiableItem> personHasVerifiableItemList =
             personHasVerifiableItemRepository.findByIdPersonAndIdVerifiableItemOrderByTimeStampDesc(person.getIdPerson(), "ema");
        if (!personHasVerifiableItemList.isEmpty()) {
            for (PersonHasVerifiableItem emailVerifiableItem : personHasVerifiableItemList) {
                if (emailVerifiableItem.isSuccess()) {
                    assertEquals(person.getIdPerson(),emailVerifiableItem.getIdPerson());
                    break;
                }
            }
        }
    }

    @Given("^my person status is "(.*?)"$")
    public void my_person_status_is(String personStatus) throws Throwable {
        person = personRepository.findByUserName(username);
        assertEquals(personStatus, person.getIdPersonStatus());
    }

    @When("^I provide my credentials$")
    public void I_provide_my_credentials() throws Throwable {
        LoginRequest loginRequest = new LoginRequest();
        loginRequest.setUserId(username);
        loginRequest.setPassword(password);
        loginResponse = pokerLoginService.login(loginRequest);
    }

    @And(
        "^I should receive the following demographic data "([^"]*)" "([^"]*)" "([^"]*)" "([^"]*)" "" +
        "([^"]*)" "([^"]*)" "([^"]*)"$")
    public void I_should_receive_the_following_demographic_data(String firstName,
                                                                String lastName,
                                                                String address1,
                                                                String address2,
                                                                String city,
                                                                String state,
                                                                String zip)
    throws Throwable {
        assertEquals(firstName, StringUtils.trimToEmpty(loginResponse.getFirstName()));
        assertEquals(lastName, StringUtils.trimToEmpty(loginResponse.getLastName()));
        assertEquals(address1, StringUtils.trimToEmpty(loginResponse.getStreetAddress1()));
        assertEquals(address2, StringUtils.trimToEmpty(loginResponse.getStreetAddress2()));
        assertEquals(city, StringUtils.trimToEmpty(loginResponse.getCity()));
        assertEquals(state, StringUtils.trimToEmpty(loginResponse.getIdState()));
        assertEquals(zip, StringUtils.trimToEmpty(loginResponse.getZipCode()));
    }

    @And("^I should have a third party authentication token$")
    public void I_should_have_a_third_party_authentication_token() throws Throwable {
        assertNotNull(StringUtils.trimToNull(loginResponse.getThirdPartyAuthenticationToken()));
    }
}

Now that I have the feature and the steps created, I added in the Cucumber runner in
…/src/test/java/com/cdi/igs/adapter/cucumber/TestCucumber.java. Notice the glue property of @CucumberOptions. That defines directories to scan.

package com.cdi.igs.adapter.cucumber;</code>

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

/**
* JUnit test class for cucumber.
* @author norris.shelton
*/
@RunWith(Cucumber.class)
@CucumberOptions(
tags = {},
glue = {"com.cdi.igs.adapter.cucumber", "cucumber.api.spring"})
public class TestCucumber {
}

In the top of the LoginSteps class, there was a ContextConfiguration annotation.

@ContextConfiguration("classpath:TestCucumber-context.xml")

That Spring context config file is located in …/src/test/resources/TestCucumber-context.xml and thee contents of that are as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath*:TestAdapter-context.xml"/>
</beans>

It merely says use whatever Spring configuration has already been defined for the rest of the project.

November 20th, 2014

Posted In: Cucumber, Integration Tests, Java, JUnit, Spring, TDD, Test Driven Development, Unit Tests

Tags: , , , , , , , , ,

8 Comments

  • Aiming says:

    I am using spring version 3.2.1 release and cucumber version 1.2.0 and it does not work. Autowired bean is null. what spring version you use?

    • sheltonn says:

      I was using Spring 4.1.1.RELEASE and Cukes 1.2.3. These are my Maven dependencies, but it sounds like your problem is in your Spring configuration. Maybe you aren’t scanning the correct packages.

              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-test</artifactId>
                  <scope>test</scope>
                  <exclusions>
                      <exclusion>
                          <artifactId>commons-logging</artifactId>
                          <groupId>commons-logging</groupId>
                      </exclusion>
                  </exclusions>
              </dependency>
      
              <dependency>
                  <groupId>info.cukes</groupId>
                  <artifactId>cucumber-java8</artifactId>
                  <version>${cucumber.version}</version>
                  <scope>test</scope>
              </dependency>
              <dependency>
                  <groupId>info.cukes</groupId>
                  <artifactId>cucumber-junit</artifactId>
                  <version>${cucumber.version}</version>
                  <scope>test</scope>
              </dependency>
      
  • Aiming says:

    Sheltonn, thanks for your quick response! After I changed the version, it works now! It does seems a version compatibility issue.

  • […] a follow-up to Cucumber Springframework Integration, I needed to get more flexibility to control when Cucumber was ran. With the current configuration, […]

  • Nitram says:

    Using Spring java is there a way someone can do a Cucumber test not through the screen but through the controller?

    • sheltonn says:

      Yes. I have seen it where the Cucumber is used to run Selenium. The Selenium web driver can be used to make the HTTP requests by filling in forms, submitting forms, then verifying the content that is returned in the response.

  • Aliyu Fonyuy says:

    Do you mind uploading a sample source for the rest of the application? Am new to both Spring and Cucumber and interested in seeing how you configured the app using spring.

    • sheltonn says:

      Here is some of it. It’s pretty complex.

      LoginSteps.java uses the TestCucumber-context.xml via @ContextConfiguration(“classpath:TestCucumber-context.xml”)

      TestCucumber-context.xml is a straight import of TestAdapter-context.xml. This was chosen so that the Cucumber configuration could be different than the Junit configuration. In hindsight, they were exactly the same, so this step could be removed.

      TestAdapter-context.xml is a component scan of the test packages (Junit and Cucumber) and an import of test-cdi-core-context.xml. NOTE that this is in another application. A bad idea to have these so closely coupled.

      testcdi-core-context.xml has a bunch of other imports that are needed for it to run. Nothing that is Cucumber specific.

      TestCucumber.java in package com.cdi.igs.adapter.cucumber configures Cucumber for processing. It is told where the Cucumber feature files are and where the Cucumber libraries are (e.g. glue = {“com.cdi.igs.adapter.cucumber”, “cucumber.api.spring”}).

      That should be all of it.

Leave a Reply

Your email address will not be published. Required fields are marked *

LinkedIn Auto Publish Powered By : XYZScripts.com