This workshop is designed to help you start or improve your Test Driven Development and Behaviour Driven Development skills.
The examples you will see in this workshop are designed to demonstrate the advantages and technicalities of TDD. The intention is to represent real-world scenarios, however sometimes that will not be possible in favour of simplicity.
Test Driven Development or Test First Development is a process that consists of turning the requirements of the software application into specific test cases (acceptance criteria) and then implement the source code.
This process uses the red/green/refactor pattern and consists of the following steps:
- Create Test
- Run Tests (should fail - Red)
- Write Code
- Run Tests (should pass - Green)
- Refactor
Repeat
Behaviour Driven Development is a methodology that specifies acceptance criteria using a syntax that can be managed by business and by technology. The most well known implementation for this syntax is Gherkin.
The Gherkin syntax has 3 main components that are represented by the following keywords:
-
Feature - maps to a feature of the software. e.g.: Login
-
Scenario - maps to a particular scenario of the usage of the feature.
-
Step - a step of the scenario. A step starts with one of the following keywords:
- Given - used for definition of context.
- And or When - used for events.
- Then or But - used for assertions.
- Quick start
- Testing Tools/Frameworks
- Naming conventions
- AAA Pattern
- Mocks & Stubs
- Instant Feedback Tools
- Examples
Prerequisites
- You have an IDE or a text editor (e.g.: IntelliJ IDEA)
- You have Maven installed
We will be using a few tools/frameworks to facilitate our job.
- JUnit - Unit Testing Framework
- mockito - Mocking Framework for Unit Tests
- junit-dataprovider - Data Provider Runner for JUnit
- Cucumber-JVM - A BDD testing framework implementation for Java
Tests serve 3 purposes:
- Acceptance Criteria - Ensures developed code meets specification
- Regression Testing - Ensures new changes don't impact previous developed code
- Documentation - Demonstrates how the application behaves
To achieve proper documentation, a good starting point is to create naming conventions for the tests.
You can define your own conventions keeping in mind that the test methods should clearly identify:
- What is being tested
- What is the Scenario (Input)
- What should be the outcome (Output)
Example with a traditional approach (simple JUnit):
@Test
public void testSum_BothNumbersArePositive_ShouldReturnPositiveNumber() {
...
}
The method name should be read as :
Test sum IF both numbers are positive THEN should return positive number.
Example with a BDD approach:
Feature: Calculator
The calculator supports the sum operation.
Scenario: Adding positive numbers
Given I use a calculator
When I add positive numbers
Then The result should be positive
Tests typically follow the AAA pattern:
- Arrange - Setup of the Scenario, e.g.: creating the input data
- Act - Executing the action/method
- Assert - Validation of the outcome
Example:
@Test
public void testSum_BothNumbersArePositive_ShouldReturnPositiveNumber() {
// Arrange
int a = 10;
int b = 20;
Calculator calc = new Calculator();
// Act
int result = calc.sum(a, b);
// Assert
Assert.assertTrue(result > 0);
}
Mocks and Stubs are used to facilitate testing by solving the problem of dependencies.
When the code you are implementing has a dependency, using this technique, you create a fake object that emulates that dependency. If you are required to define specific return values to emulate a certain scenario then you'll need to use a stub otherwise you'll simply use a mock.
Example:
- Mock
provider = mock(PaymentProviderInterface.class);
broker = new PaymentBroker(provider);
- Stub
provider = mock(PaymentProviderInterface.class);
broker = new PaymentBroker(provider);
when(provider.isAvailable()).thenReturn(false);
Feedback is one of the most important things in the development world, the sooner you get it the better.
Typically most of the feedback comes from the user/client of your software, but you should be getting it before you ship it.
There are plenty of tools out there that can help you with this. In this workshop we will be using the following:
-
Automation Server - Allows you to automate the test execution (Continuous Integration) and other routines associated with it (Continuous Delivery/Continuous Deployment). In this particular case we are using Travis CI.
You can check the current status of the workshop project by clicking the following badge:
-
Static Code Analyzer - Allows you to continuously inspect the quality of the code by detecting issues and providing suggestions to solve them. In this project we are using SonarCloud.
You can check the current status of the workshop project by clicking the following badge:
-
Kanban Board - Allows you to track your project's work with a workflow visualization tool. In this project we are using Trello.
You can check the current status of the workshop project by clicking the following link:
- Calculator - Simple example to get you started
- LoginManager - Working with exceptions
- StringProcessor - Working with data providers
- PaymentBroker - Working with dependencies, mocks and stubs