codecentric

ATDD and Thucydides – part 1 of 2

In a world where test driven development is becoming more important every day, one of the biggest challenges for technical people is to translate questions from non-technical people into technical solutions. One of the methods to bridge the gap between non-technical and technical people is choosing for ATDD (acceptance test driven development).

ATDD

ATDD allows for example agile teams to have a common understanding of the requirements and expectations of stories in the backlog.  This can be done for instance by having a mini-workshop with people who know the the domain, developers and testers. These three different roles can help to specify a story by defining, clarifying and verifying. By having these three roles together a common understanding or specification should be and can be reached.

A common understanding of a specification should be documented, but also needs to be tested if the specification is implemented correctly. To bridge the gap between documentation and test a DSL (domain specific language) should be used. A DSL helps the people who know the domain, developers and testers to have a common language to communicate specifications.

There are currently different DSLs already available that can help you to have specification in a readable format for domain representers, developers and testers. These DSLs also allow you to have these specifications automatically to be tested. (examples of these DSLs are implemented in frameworks like easyb, cucumber and jBehave) By choosing a language to define specifications, team members are able to communicate features with each other in a unified way.

JBehave example from the TDD training application:

Scenario: Calculate triangle type EQUILATERAL

Given The triangle form is loaded
When side A is 2, side B is 2 and side C is 2
And submits the triangle form
Then the triangle type should be EQUILATERAL

Scenario: Calculate triangle type ISOSCELES

Given The triangle form is loaded
When side A is 2, side B is 2 and side C is 3
And submits the triangle form
Then the triangle type should be ISOSCELES

Doing ATDD for web applications can also be done, by choosing test framework like Fitnesse or Thucydides. Thucydides will be explained in the second part of the blog.

Hylke Stapersma

 

ATDD and Thucydides – part 2 of 2

In the previous post I described you can use ATDD for closing the gap between business, tester and development, in the second part of the post I will describe Thucydides a powerful tool for doing ATDD.

Thucydides

For testing applications on the web, selenium can be used. Selenium is a framework that allows tests to be written to work on multiple browsers in a generic way. These tests can be defined by recording them in the browser or to be written down in code. When recording selenium tests a problems can occur when the state changes of the web application, an expected element could become unavailable and fail your test. When defining tests in code, it could be possible that tests lose their readability for testers and people who represent the domain.

Keeping tests readable, reusable and repeatable could be a challenge, Thucydides is a selenium extension that allows people from the domain, developers and testers to have those tests. Thucydides is build around the idea that the tests tell the story of the application and are readable for everyone, Thucydides is a ATDD testing framework for the web.

Thucydides keeps the tests readable and reusable by making use of stories, features, acceptance criteria (tests) and steps. Stories define a high level description of a set of features for example user management. A story can be defined in features for example creating and removing a user. These features have acceptance criteria for example “a user manager is able to sort users on the user overview page”. A acceptance criteria is a collection of steps that have to be done to perform the action.

Implementing tests or acceptance criteria, different test languages/tools can be chosen Thucydides supports test tools like EasyB, jBehave and JUnit.  When implementing tests with Thucydides the following concepts are in important:

  • Page(model), a representation of a web page where for example links and buttons are considered properties of a page. The state of a page is represented in a page(model).
  • Steps, a grouping(library) of actions that can be performed on a page. For example clicking on a link on a page.
  • Test, a collection of steps defining a user operation and verify if the operations were done correctly.

The big difference for only choosing selenium is the ability to have steps. Steps adds a abstraction level, that allows the implementer of tests to create a library of operations that can be done on a web page. These libraries can be reused in other tests.

For running Thucydides tests maven is used, maven is a framework that allows to automate build, documentation and reporting processes. After configuring Thucydides in the project pom.xml, tests can be run by using the following command. ‘mvn verify’ (Make sure the web application is available while starting the tests.)

Reporting and documentation are an important part of Thucydides, the reports represent the implementation state of the application. The will also tell the (historic) story of the application, which acceptance criteria are met, a which steps are taken to meet these acceptance criteria. In the reports a drilldown is possible from stories to the actual steps that have be taken to test the story.

Example of a Thucydides report:

For training purposes we’ve created a training application that is based on Weinburg-Myers triangle program example. This training application contains examples of wide range of tests. This training application also contains examples making use of Thucydides. (For running tests please read the README file on github https://github.com/codecentric/TDDTrainingApplication/blob/master/README.md)

The Thucydides concepts are also available in the training application, we use a page model for the representation of a web page.

public class TriangleCalculationPage extends PageObject {
 
public TriangleCalculationPage(WebDriver driver) {
super(driver);
}
 
@FindBy(name = "triangleSide1")
private WebElement inputSide1;
 
@FindBy(name = "triangleSide2")
private WebElement inputSide2;
 
@FindBy(name = "triangleSide3")
private WebElement inputSide3;
 
@FindBy(css = "button[type='submit']")
private WebElement submitButton;
 
public boolean hasInputSide1() {
return element(getInputSide1()).isCurrentlyVisible();
}
 
public boolean hasInputSide2() {
return element(getInputSide2()).isCurrentlyVisible();
}
 
public boolean hasInputSide3() {
return element(getInputSide3()).isCurrentlyVisible();
}
 
public boolean hasSubmitButton(){
return element(getSubmitButton()).isCurrentlyVisible();
}
 
}

In the TDD training application there are steps to defined for operation that can be done on a web page.

public class TriangleCalculationSteps extends ScenarioSteps{
 
public TriangleCalculationSteps(Pages pages) {
super(pages);
}
 
@Step("Open triangle calculation form")
public void openTriangleCalculationForm(){
getPages().get(TriangleCalculationPage.class).open();
}
 
@Step("Fill in triangle sides")
public void fillInTriangleSides(String triangleSide1,String triangleSide2,String triangleSide3){
TriangleCalculationPage triangleCalculationPage = getPages().currentPageAt(TriangleCalculationPage.class);
triangleCalculationPage.getInputSide1().clear();
triangleCalculationPage.getInputSide2().clear();
triangleCalculationPage.getInputSide3().clear();
triangleCalculationPage.getInputSide1().sendKeys(triangleSide1);
triangleCalculationPage.getInputSide2().sendKeys(triangleSide2);
triangleCalculationPage.getInputSide3().sendKeys(triangleSide3);
}
 
@Step("Submit triangle calculation form")
public void submitTriangleSideForm(){
TriangleCalculationPage triangleCalculationPage = getPages().currentPageAt(TriangleCalculationPage.class);
triangleCalculationPage.getSubmitButton().click();
}
 
@Step("Should see the error page")
public void shouldBeAtErrorPage(){
Assert.assertTrue("Should see the error page", getPages().isCurrentPageAt(TriangleCalculationErrorPage.class));
}
 
@Step("Should see the success page")
public void shouldBeAtSuccessPage(){
Assert.assertTrue("Should see the success page", getPages().isCurrentPageAt(TriangleCalculationSuccessPage.class));
}
 
@Step("Expect triangle type on success page")
public void expectTriangleTypeOnSuccessPage(TriangleType triangleType){
TriangleCalculationSuccessPage triangleCalculationSuccessPage = getPages().currentPageAt(TriangleCalculationSuccessPage.class);
Assert.assertTrue("Triangle success page should have triangle type element",triangleCalculationSuccessPage.hasTriangleTypeSpan());
Assert.assertThat("Triangle type is not correct",triangleType, Matchers.equalTo(TriangleType.valueOf(triangleCalculationSuccessPage.getTriangleTypeSpan().getText())));
}
 
}

By having these steps and pagemodels the following stories / scenarios can now be tested. These tests can by run with JUnit for example.

@RunWith(ThucydidesRunner.class)
@Story(Application.TriangleCalculation.Success.class)
public class TriangleCalculationSuccessStory {
 
@Managed(uniqueSession = true)
public WebDriver webDriver;
 
@Getter
@ManagedPages
public Pages pages;
 
@Steps
public TriangleCalculationSteps steps;
 
@Test
@Title("Test triangle type EQUILATERAL")
public void testNonNumericEquilateral() {
fillInTriangleCalculationForm("2", "2", "2", TriangleType.EQUILATERAL);
}
 
@Test
@Title("Test triangle type ISOSCELES")
public void testNonNumericInputSide2() {
fillInTriangleCalculationForm("2", "3", "2", TriangleType.ISOSCELES);
}
 
@Test
@Title("Test triangle type SCALENE")
public void testNonNumericInputSide3() {
fillInTriangleCalculationForm("2", "3", "4", TriangleType.SCALENE);
}
 
private void fillInTriangleCalculationForm(String side1, String side2, String side3, TriangleType triangleType) {
steps.openTriangleCalculationForm();
steps.fillInTriangleSides(side1, side2, side3);
steps.submitTriangleSideForm();
steps.shouldBeAtSuccessPage();
steps.expectTriangleTypeOnSuccessPage(triangleType);
}
 
}

Conclusion

ATDD allows domain representatives, testers and developers to work in a more uniform way by having tests written down in a uniform language everybody understands. A uniform language or DSL can be interpreted by people and machines, which allows for readability and repeatability.

For acceptance testing web application frameworks like Thucydides and Fitness can be used. Thucydides allows tests or acceptance criteria to be written for different test tools like EasyB, jBehave or JUnit.

Links

Thucydides
TDD Training application
TDD Weinburg-Myers example
ATDD
DSL
EasyB
Cucumber
JBehave
Selenium
Fitnesse

Hylke Stapersma

 

Pros and Cons of the LCOM4 metric in Sonar

In our projects, we use sonar to detect quality flaws in our sources as early as possible. An important metric is LCOM4: Lack of Cohesion of Methods IV. It measures how related the fields and methods in a class are. If everything is related within a class, that’s the best case. If LCOM4 is greater than 1, the class is suspicious to violate the Single Responsibility Principle. The class might be responsible for more than one thing, and is a candidate to be split into two ore more classes in a refactoring. At least in Theory…

(read more…)

Andreas Ebbert-Karroum