Skip to Content
Course content

129: Behavior-Driven Testing with Cucumber Basics

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're hiring a contractor to renovate your kitchen. You don't hand them a 50-page technical manual on the chemical composition of grout or the specific voltage of the wiring. Instead, you give them a set of requirements in plain English: "When I flip this switch, the island lights should turn on," or "Given that the dishwasher is running, the sink should still have water pressure." You're describing the behavior of the kitchen, not the implementation details. If the lights turn on, you don't care if they used copper or silver wiring; the requirement was met.

That's exactly what Cucumber does for your Java code. It acts as a bridge between the "business speak" (what the software should actually do) and the "dev speak" (the JUnit or TestNG code that verifies it). It allows us to write tests in a language called Gherkin, which is essentially a structured way of writing English that a computer can actually parse.

Writing the Story in Gherkin

In Cucumber, we start with a .feature file. This is where the "contract" lives. I always tell my juniors to treat this file as the single source of truth—if a product manager can't read this and agree with it, your test is useless.

Let's look at a real scenario: a shopping cart total calculation. Instead of a method named testCartTotalWithTax(), we write this:

Feature: Shopping Cart Calculations
  Scenario: Calculate total price for a single item
    Given the shopping cart is empty
    When I add a "Mechanical Keyboard" priced at 120.00
    Then the total price should be 120.00

Notice the keywords: Given (the starting state), When (the action), and Then (the expected outcome). It's simple, but the magic happens when we map these specific sentences to Java methods.

Translating English into Java

Now, Cucumber needs a "translator." This is where the Step Definition class comes in. This is just a regular Java class where each method is annotated with a regex or a cucumber expression that matches the text in your feature file.

Here is how I'd implement the translation for the keyboard example:

public class ShoppingCartSteps {
    private ShoppingCart cart;
    private double finalTotal;

    @Given("the shopping cart is empty")
    public void the_shopping_cart_is_empty() {
        cart = new ShoppingCart();
    }

    @When("I add a {string} priced at {double}")
    public void i_add_a_priced_at(String item, Double price) {
        cart.addItem(new Item(item, price));
    }

    @Then("the total price should be {double}")
    public void the_total_price_should_be(Double expectedTotal) {
        finalTotal = cart.calculateTotal();
        assertEquals(expectedTotal, finalTotal, 0.01);
    }
}

You'll notice the {string} and {double} placeholders. These are Cucumber expressions. They let us reuse the same Java method for different data. If I add a scenario for a "Gaming Mouse" priced at 50.00, I don't need to write a new Java method; Cucumber just passes those values as arguments to the existing method.

The Glue That Holds It Together

For this to actually run, you need a "Runner" class. I've seen people struggle here because they forget that Cucumber needs to know where the feature files are and where the step definitions live. In modern Java setups, we typically use a JUnit runner.

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = "com.myapp.steps"
)
public class RunCucumberTest {
    // This class stays empty; it's just a trigger for the framework.
}

One thing to keep in mind: don't put your actual business logic inside the Step Definition methods. The step definitions should be thin. They should call methods in your actual service classes. If you start writing complex if/else blocks inside your @When methods, you've just moved the mess from your production code to your test code, which is a trap I've seen many developers fall into.




📋 Practical Task

Build a Behavior-Driven Validator for a Bookstore Discount System

You need to implement a BDD test suite for a bookstore's discount logic. The business rule is: "If a customer buys more than 3 books, they get a 10% discount on the total price."

Your requirements:

  • Create a .feature file named discount.feature with a scenario that describes adding 4 books (each priced at $10.00) and verifying the total is $36.00 (after the 10% discount).
  • Implement the BookstoreSteps Java class. You must use Cucumber expressions (like {int} or {double}) to capture the number of books and their prices.
  • Create a simple Bookstore POJO that handles the internal logic of adding books and calculating the discounted total.
  • Write the JUnit Runner class to link the feature file and the step definitions.

Verification: When you run the test, the Cucumber report should show the "Then" step passing, confirming that the 10% discount was applied correctly to the bulk order.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.