Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this short tutorial, we're going to learn about Cucumber Backgrounds, which is a feature that allows us to execute some sentences for each test of a Cucumber Feature.

2. Cucumber Background

First, let's explain what the Cucumber Background is. Its purpose is to execute one or more sentences before each test of a feature.

But what problem are we trying to solve here?

Let's say we have a book store application we want to test with Cucumber. First of all, let's create that application, which will simply be a Java class:

public class BookStore {
    private List<Book> books = new ArrayList<>();
    
    public void addBook(Book book) {
        books.add(book);
    }
    
    public List<Book> booksByAuthor(String author) {
        return books.stream()
          .filter(book -> Objects.equals(author, book.getAuthor()))
          .collect(Collectors.toList());
    }

    public Optional<Book> bookByTitle(String title) {
        return books.stream()
          .filter(book -> book.getTitle().equals(title))
          .findFirst();
    }
}

As we can see, it's possible to add and search for books in the store. Now, let's create a few Cucumber sentences to interact with the book store:

public class BookStoreRunSteps {
    private BookStore store;
    private List<Book> foundBooks;
    private Book foundBook;
    
    @Before
    public void setUp() {
        store = new BookStore();
        foundBooks = new ArrayList<>();
    }
    
    @Given("^I have the following books in the store$")
    public void haveBooksInTheStore(DataTable table) {
        List<List<String>> rows = table.asLists(String.class);

        for (List<String> columns: rows) {
            store.addBook(new Book(columns.get(0), columns.get(1)));
        }
    }
    
    @When("^I search for books by author (.+)$")
    public void searchForBooksByAuthor(String author) {
        foundBooks = store.booksByAuthor(author);
    }

    @When("^I search for a book titled (.+)$")
    public void searchForBookByTitle(String title) {
        foundBook = store.bookByTitle(title).orElse(null);
    }
    
    @Then("^I find (\\d+) books$")
    public void findBooks(int count) {
        assertEquals(count, foundBooks.size());
    }

    @Then("^I find a book$")
    public void findABook() {
        assertNotNull(foundBook);
    }

    @Then("^I find no book$")
    public void findNoBook() {
        assertNull(foundBook);
    }
}

With those sentences, we can add books, search for them by author or title, and check whether we find them or not.

Now, everything is set for us to create our feature. We'll search for books by their author, but also by their title:

Feature: Book Store Without Background
  Scenario: Find books by author
    Given I have the following books in the store
      | The Devil in the White City          | Erik Larson |
      | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
      | In the Garden of Beasts              | Erik Larson |
    When I search for books by author Erik Larson
    Then I find 2 books

  Scenario: Find books by author, but isn't there
    Given I have the following books in the store
      | The Devil in the White City          | Erik Larson |
      | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
      | In the Garden of Beasts              | Erik Larson |
    When I search for books by author Marcel Proust
    Then I find 0 books

  Scenario: Find book by title
    Given I have the following books in the store
      | The Devil in the White City          | Erik Larson |
      | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
      | In the Garden of Beasts              | Erik Larson |
    When I search for a book titled The Lion, the Witch and the Wardrobe
    Then I find a book

  Scenario: Find book by title, but isn't there
    Given I have the following books in the store
      | The Devil in the White City          | Erik Larson |
      | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
      | In the Garden of Beasts              | Erik Larson |
    When I search for a book titled Swann's Way
    Then I find no book

This feature works fine, but it tends to be a bit verbose because we initialize the store for each test. Not only does this create a lot of lines, but if we have to update the store, we have to do it for each test. That's when Cucumber Backgrounds come handy.

3. Example

So, how to create a background creating the store for this feature? To do this, we must use the keyword Background, give it a title as we do for a Scenario, and define the sentences to execute:

Background: The Book Store
  Given I have the following books in the store
    | The Devil in the White City          | Erik Larson |
    | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
    | In the Garden of Beasts              | Erik Larson |

When we've done this, we can get rid of this sentence in the tests, letting them focus on their specificities:

Scenario: Find books by author
  When I search for books by author Erik Larson
  Then I find 2 books

Scenario: Find books by author, but isn't there
  When I search for books by author Marcel Proust
  Then I find 0 books

Scenario: Find book by title
  When I search for a book titled The Lion, the Witch and the Wardrobe
  Then I find a book

Scenario: Find book by title, but isn't there
  When I search for a book titled Swann's Way
  Then I find no book

As we can see, the scenarios are much shorter than before and the remaining sentences focus on what we're trying to test rather than setting up the data.

4. Difference with @Before

Now, let's discuss the difference between a Cucumber Background and the @Before hook. The hook also allows us to execute code before a scenario, but this code is hidden from those who are only reading the feature files. On the other hand, a Background is made of sentences that are visible in the feature files.

5. Conclusion

In this short article, we learned how to use the Cucumber Background feature. It allows us to execute some sentences before each scenario of a feature. We also discussed the difference between this feature and the @Before hook.

As usual, the code for this article can be found over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!