Tutorial 7: Acceptance Testing - McGill-ECSE429-Winter2022/tutorials GitHub Wiki

1. Introduction

An acceptance test is a formal description of the behaviour of a software product, generally expressed as an example or a usage scenario.

Tool: Cucumber

This tutorial shows how you can write acceptance tests using the Cucumber tool in a Behaviour-Driven Development approach. Following would be the key learnings:

  • Install Cucumber
  • Write Scenario using the Gherkin syntax
  • Write step definition in Java
  • Run Cucumber
  • Basic workflow of Behaviour-Driven Development (BDD)

2. Setup

You need the following:

Please follow the instructions here to install the cucumber plugin in your eclipse.

Create a new maven project with the following details:

  • groupid: org.apache.maven.archtype(quick-start)
  • Update the dependencies and properties of your POM file from here.

3. BDD (Behaviour-Driven Development)

BDD is a way for software teams to work that closes the gap between business people and technical people by:

  • Encouraging collaboration across roles to build shared understanding of the problem to be solved
  • Working in rapid, small iterations to increase feedback and the flow of value
  • Producing system documentation that is automatically checked against the system’s behaviour

For more please take a reference from here.

4. Cucumber Workflow

Before we add cucumber artifacts to our Eclipse project, let's discuss an imaginary user story. This will give you a better understanding of where cucumber fits into the software development life cycle.

The System

  • EatMore is a small but fast growing restaurant chain.
  • A team of developers, business analysts and QA testers are focused on building a website for this restaurant chain.

For such a system, what do you think will be the user stories they will be talking about?
What type of users would benefit from this website?

The Domain A problem domain is defined as a list of business objects or more specifically, business object types that we talk about in our focused area of a business problem.
In our example, we will probably be talking about things such as server, bartender, chef, food item, menu, payment, tax, gratuity, discount, inventory, and so on.

Key Players

User Story: As a manager, I should be able to add a menu item to my restaurant location's menu.

Conditions of Satisfaction The manager should be able to add a menu item with name, description, price, and calories.

Step Definition Define steps for specific meu item. e.g. Name: cucumber salad; price: 10$; Description: ______

User story -> Examples -> Business rules

the example of this exercise -> list of ** feature files**.

5. Writing sample test

Write feature file

  1. Add a feature folder in your test resource src/test/resources and create a feature file name menuManagement.feature.
  • Add the following feature in the file:
Feature: Menu Management
Scenario: Add a menu item

Given I have a menu item with name "Cucumber Sandwich" and price 20
When I add that menu item
Then Menu Item with name "Cucumber Sandwich" should be added
  • Important points to notice: name of the file and order of the terms.
  1. Run the feature file:
  1. Analyze and understand the result.

Write step definition

  1. Create a package stepDefinition as follows:
  1. Create a simple java class with name MenuManagementSteps as follows:
  1. Write the following step definition:
@Given("I have a menu item with name {string} and price {int} \\/\\/represent precondition")
  public void i_have_a_menu_item_with_name_and_price_represent_precondition(String string, Integer int1) {
      // Write code here that turns the phrase above into concrete actions
      throw new io.cucumber.java.PendingException();
}

@When("I add that menu item                                             \\/\\/action")
  public void i_add_that_menu_item_action() {
      // Write code here that turns the phrase above into concrete actions
      throw new io.cucumber.java.PendingException();
}

@Then("Menu Item with name {string} should be added          \\/\\/result")
  public void menu_item_with_name_should_be_added_result(String string) {
      // Write code here that turns the phrase above into concrete actions
      throw new io.cucumber.java.PendingException();
}
  1. Observe a few things such as: Name of the method, annotation, values inside the annotation.

  2. Run and analyze the exception:

  1. Write the logic for step definition and source class for it.
public void i_have_a_menu_item_with_name_and_price_represent_precondition(String newMenuItemName,Integer price) {
        RestaurantMenuItem NewMenuItem;
	  
        NewMenuItem = RestaurantMenuItem(newMenuItemName, "", price);
  }
  • Add a class RestaurantMenuItem and RestaurantMenu as source class with the following logic

public class RestaurantMenuItem {

private String MenuItemName;


public RestaurantMenuItem(String menuItemName, String description, int price) {
	super();
	MenuItemName = menuItemName;
	Description = description;
	Price = price;
}
public String getDescription() {
	return Description;
}
public void setDescription(String description) {
	Description = description;
}
public int getPrice() {
	return Price;
}
public void setPrice(int price) {
	Price = price;
}
public String getMenuItemName() {
	return MenuItemName;
}
private String Description;
private int Price;

@Override
public boolean equals(Object obj) {
     if ((obj == null)
    		 || (getClass() != obj.getClass())) {
         return false;
     }
     
     RestaurantMenuItem OtherMenuItem = (RestaurantMenuItem) obj;

     return (OtherMenuItem.getMenuItemName()).equals(this.MenuItemName);

}

}

public class RestaurantMenu {

  ArrayList<RestaurantMenuItem> MenuItems = new ArrayList<RestaurantMenuItem>();


  public boolean addMenuItem(RestaurantMenuItem newMenuItem) {
	  if (DoesItemExist(newMenuItem)) {
		  throw new IllegalArgumentException("Duplicate Item");
	  }
			  return MenuItems.add(newMenuItem);
  }

  public boolean DoesItemExist(RestaurantMenuItem newMenuItem) {
	  boolean Exists = false;
	  if (MenuItems.contains(newMenuItem)) {
		  Exists = true;
	  }
	  return Exists;
  }

}

  1. Run as a feature and analyze the result:

6. Test Runner

We are not going to run all your test cases from Eclipse. We are going to be running those from a tool like Maven and we need a test runner file to do that. So let's implement that.

  1. Add a package name testrunners and add a class named MenuManagementTest as follows:
  • Add the following code:
@Suite @IncludeEngines("cucumber") @SelectClasspathResource("features") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") public class MenuManagementTest {

}

  1. Go to your cmd and change the directory to your project and run mvn test :

7. Tag, Background, and Hooks

A tag is just a value attached to a Cucumber construct. Attaching a tag, helps you organize your Cucumber constructs because you can filter a feature or scenario based on tag value or values.
A common practical application is to test a subset of features or scenarios in a build process. Perhaps you have a specific set of features that take a long time to run and you want to filter those out from your continuous build process. You could include those features in a specialized nightly build process by applying the tag-based filter.

  • OR, AND, and not operations in tags

  • Maven test with tags : mvn test -Dcucumber.options=" --tags '@RegualrTest'"

Background is something you add to a feature file, and it's syntactically very similar to a Scenario. The Background steps run before each Scenario in a feature file. Another important aspect of Background is that it is visible to all stakeholders because it's part of your Gherkin feature file.
Follow a demo on screen.

If you have worked with unit testing tools before, you have probably seen setup and teardown methods. That's exactly what Cucumber Hooks use. Cucumber Hooks are classes that contain methods that have special annotations, namely before and after, and those methods execute before or after each scenario.

Reference for more exploration.

⚠️ **GitHub.com Fallback** ⚠️