Nicolas Frankel is an IT consultant with 10 years experience in Java / JEE environments. He likes his job so much he writes technical articles on his blog and reviews technical books in his spare time. He also tries to find other geeks like him in universities, as a part-time lecturer. Nicolas is a DZone MVB and is not an employee of DZone and has posted 226 posts at DZone. You can read more from them at their website. View Full User Profile

Automate Your Integration Tests

09.21.2010
| 9857 views |
  • submit to reddit

Software testing traditionally has been separated between unit testing – testing classes in isolation – and integration testing – testing across all layers. Whereas unit testing is the domain of developers, integration testing is the domain of analysts. Moreover, most of the time, those tests are not automated and are painfully reexecuted by hand each time they are needed. This means that your build process has a safeguard harness on the unit level but nothing on the feature level (at least nothing remotely automated).

In order to further streamline the build process, it would be order to also automate integration tests. I already have some successful experience with integration testing with batches. Batches are very simple to test in this way since they lack a very hard-to-test feature, namely GUI. I developed those tests with the TestNG framework, mainly because TestNG provides the way to order test methods.

Yet, those tests I was pleased with lack one essential feature: the analyst point-of-view. It’s me, as developer, that created them and as such, they may not adress the uses cases deemed critical to the business.

What’s essential is what lies between the description of the tested use cases in plain text and their implementations in Java. My TestNG tests were developed by the developer, for the developer, in Java and couldn’t be read by a typical business analyst. At the time, it was the best I could do but a thread inside my head longed to bridge the gap between developer and analyst points of view. Luckily, I have found (at least I think) the right tool in order to solve this.

This tool is JBehave, and as you can guess from its name, it advocates for Behaviour Driven Development. Its strongest point is that the business analyst is a the root of the process. Given a few simple rules, he can describe use cases in plain language. Then, the developer ties these stories, as they are called in JBehave, into the code. There are only a few rules for these descriptions:

  • describe the initial situation with the Given keyword
  • describe events with the When keyword
  • describe expectations with the Then keyword

Let’s take a simple example, as it would be written by a business analyst :

Given a student
Given a course
When the student registers in the course
Then the course must have the student as one of its student

Now, for each line, the developer creates a method and adds the right annotation to it:

public class AddCourseSteps {

    private Student student;

    private Course course;

    @Given("a student")
    public void aStudent() {

        this.student = new Student("dummy");
    }

    @Given("a course")
    public void aCourse(String label) {

        this.course = new Course("anotherDummy");
    }

    @When("the student registers in the course")
    public void heRegistersInACourse() {

        student.addCourse(course);
    }

    @Then("the course must have the student as one of its student")
    public void courseMustHaveStudent() {

        assertTrue(course.getStudents().contains(student));
    }
}

Notice how the “business” semantics is coded in the Java language. This example is of course trivial but higher-level stories would be treated just the same.

Running the story is just coding the test class in itself, which will tie the plain text description and the steps class and make the test class runnable in your favorite build tool and/or IDE. This wil produce the following trace:

Given a student
Given a course
When the student registers in the course
Then the course must have the student as one of its student (FAILED)

The FAILED part is of course only there is the test fails. You can object this is much ado about nothing, but only until now, because JBehave also let you parameterize your tests from the textual description, letting you write this:

Scenario: students are ranked according to marks

Given a course
Given a student named John Doe
Given a student named Jane Doe
When the first student obtains a A
When the second student obtains a B
Then first student is ranked 1 in the course
Then second student is ranked 2 in the course

Scenario: students are ranked according to marks or not ranked if they have no marks

Given a course
Given a student named John Doe
Given a student named Jane Doe
When the first student obtains a A
When the first student obtains a not_present
Then first student is ranked 1 in the course
Then second student is ranked not_ranked in the course

This can easily be written by business analysts.

To be frank, I didn’t use JBehave in any of my projects yet, but I intend to in the near future. I would rather be interested if anyone could give me feedback, mainly on v3.0. Otherwise, I encourage you to have a look at the JBehave site.

You can find the sources for the first example here in Maven/Eclipse format. I’ll let the second example as an exercise for the curious reader.

From http://blog.frankel.ch/automate-your-integration-tests

Published at DZone with permission of Nicolas Frankel, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Christian Schli... replied on Tue, 2010/09/21 - 7:50am

Interesting post. However, for what it achieves it seems pretty bloated. I imagine writing a real use case like this might get my fingers bleeding. And I can't imagine a business analyst would like to read the result.

Alexander Radzin replied on Wed, 2010/09/22 - 3:09am

Thank you for very valuable information. I spent a couple of hours reading about BDD and enjoyed to learn a new stuff.

I agree that the code snippet your wrote is very readable. But don't you think it is too verbose? The same can be written using usual JUnit4 framework as following:

public class AddCourseStepsTest {
    @Test
    public void courseMustHaveStudent() {
        Student student = new Student("dummy");
        Course course = new Course("anotherDummy");
        student.addCourse(course);
        assertTrue(course.getStudents().contains(student));
    }
}

This code snippet is 9 lines long. Yours contains 30 lines.

Now let's assume that we want to veryfy that the system function well for 0, 1, 2, ... N students. And for different number of courses. To do this I usually implement parametrized scenario like the following:

public class AddCourseStepsTest {
    @Test 
    private void studentsAtCourse(
                  String[] studentNames, String[] courseNames) { /*GIVEN */

        // GIVEN
        Student[] students = new Student[studentNames.length];
        for (int i = 0; i < studentNames.length;  i++) {
            students[i] = new Strudent(studentName[i]);
        }
        Course[] courses = new Course[courseNames.length];
        for (int i = 0; i < courseNames.length;  i++) {
            courses[i] = new Strudent(courseName[i]);
        }

        // WHEN
        for (Course c : courses) {
            for (Student s : students) {
                student.addCourse(c);
            }
        }


        // THEN
        for (Course c : courses) {
            for (Student s : students) {
                assertTrue(course.getStudents().contains(student));
            }
        }
    }
}

 

 Now I can use it either implementing method for each combination of arguments or by creating TestSuite dynamically. So, I achieve maximal code reuse when I codig my tests using JUnit.

The question is: is it posible to achieve code reuse and create parametrized scenarios using BDD? It seems that our tools are more limited when we are using BDD relatively to the traditional JUnit.

 

 

Nicolas Frankel replied on Wed, 2010/09/22 - 4:37am in response to: Alexander Radzin

Hi Alexander,

Thanks for your input. Of course you're right: the JBehave test code is verbose and complex compared to your JUnit one.

IMHO, the point lies not there: it is in making the test available to the business analyst. Can you imagine poor analyst reading the JUnit? I do not. JBehave has the potential to cross the bridge between analyst and developer. That's where its value lies.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.