Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there BDD java framework capable of reusing Given, Then? (with varying When step )

I am looking for BDD java framework with possibility to reuse Given & Then for Unit and Integration tests.

In other words 1. Given some precondition. 2. When - depending on the environment 3. Then verify results of When

I want to be able by changing When, and keeping Given and Then intact, change the type of the test, for example in simple REST service:

  1. UNIT test
    • Given
      • generates some POJO object
    • When
      • receives POJO from Given
      • calls internal service with this POJO
      • receives result in POJO form from the service
      • forwards received POJO to Then
    • Then
      • verifies POJO from When
  2. INTEGRATION test
    • Given
      • generates some POJO object
    • When
      • receives POJO from Given
      • encrypts POJO in external service format
      • calls external service
      • receives result in external service format from exposed service
      • transforms received result in POJO
      • forwards received POJO to Then
    • Then
      • verifies POJO from When

So in example, Given and Then behave the same way, for both integration and unit tests, and by simply changin When the scope of the test goes from UNIT to INTEGRATION.

Can someone point me in the right direction?

I don't want to reinvent the wheel

like image 558
mavarazy Avatar asked Feb 12 '13 06:02

mavarazy


People also ask

How does BDD framework work?

BDD test automation frameworks read executable specifications written in plain text (e.g., Gherkin or other domain-specific languages, or DSLs) and validate that the software does what those specifications promise. The framework generates a report that indicates a success or failure for each specification.

What is true about BDD?

BDD is a development approach using a specific mindset. It is the logical extension of Test Driven Development (TDD), focussing on the business intent and expected behaviour of the system. Requirements are specified in a domain specific language (DSL), readable by both technical and non-technical people.

What are the main features of cucumber explain how you implemented Cucumber BDD framework in your project?

Cucumber is a very popular BDD tool. It is easy to read and can be understood by all stakeholders including technical and non-technical person. Create feature file in which define the feature and scenarios step by step using Gherkin language. Create Testrunner file.

Is TestNG a BDD framework?

Yes TestNG is a framework. Cucumber is a tool that supports Behaviour-Driven Development (BDD) Approch. TestNG having its own approach to maintain and execute test cases.


2 Answers

Disclamer: I am the author of JGiven.

JGiven exactly provides that. It is a BDD framework for Java where scenarios are built by so-called stage classes. For your example you need four stage classes: GivenInput, WhenInternalService, WhenExternalService, and ThenOutput. Then you can write two tests:

Unit test for the internal service:

public class InternalServiceTest extends 
       ScenarioTest<GivenInput, WhenInternalService, ThenOutput> {

    @Test
    public void internal_service_works_as_expected() {
       given().some_input();
       when().the_internal_service_is_called();
       then().the_result_is_correct();
    } 
}

Integration test for the external service:

public class ExternalServiceTest extends 
       ScenarioTest<GivenInput, WhenExternalService, ThenOutput> {

    @Test
    public void external_service_works_as_expected() {
       given().some_input();
       when().the_external_service_is_called();
       then().the_result_is_correct();
    } 
}

The stage classes then look something like this:

public class GivenInput extends Stage<GivenInput> {
    @ProvidedScenarioState
    InputPojo input;

    public GivenInput some_input() {
       input = new InputPojo();
       return self();
    }
}

public class WhenInternalService extends Stage<WhenInternalService> {
    @ExpectedScenarioState
    InputPojo input;

    @ProvidedScenarioState
    OutputPojo output;

    public WhenInternalService the_internal_service_is_called() {
        output = new InternalService().invoke(input);
        return self();
    }
}

public class WhenExternalService extends Stage<WhenExternalService> {
    @ExpectedScenarioState
    InputPojo input;

    @ProvidedScenarioState
    OutputPojo output;

    public WhenExternalService the_external_service_is_called() {
        ExternalInput externalInput = transformToExternal(input);
        ExternalOutput externalOutput = new ExternalService().invoke(external);
        output = transformToInternal(externalOutput);
        return self();
    }
}

public class ThenOutput extends Stage<ThenOutput> {
    @ExpectedScenarioState
    OutputPojo output;

    public ThenOutput the_result_is_correct() {
        assertThat(output).isNotNull();
        return self();
    }
}

Note that the step methods are written in a fluent-interface style to be able to chain multiple conditions (not needed in your example though).

like image 117
Jan Schaefer Avatar answered Sep 22 '22 12:09

Jan Schaefer


If you're using Java 8 then you should have a look at this github project.

Using this you could achieve what you want without the hassle of creating classes. This is due to the use of Generics + Java 8 Lambdas.

Here are some basic test samples:

@Test
public void basicFlowTest() {
 given(1)
  .when("multiplying by 2", givenValue -> 2 * givenValue)
  .then("value should be even", whenValue -> whenValue % 2 == 0);
}

public void multiTypeFlowTest() {
 LocalDateTime localDateTime = LocalDateTime.now();
 DayOfWeek expectedDay = localDateTime.getDayOfWeek();

 given(localDateTime)
  .when("retrieving current day", date -> date.getDayOfWeek())
  .then("days should match", day -> expectedDay == day);
}

@Test
public void assertFlowTest() {
 Integer primeNumber = 17;
 given("a prime number", primeNumber)
  .when("finding dividers naively", number -> IntStream.rangeClosed(1, number)
   .boxed().filter(value -> number % value == 0).collect(Collectors.toList()))
  .then(dividers -> {
   assertEquals("should have two dividers", 2, dividers.size());
   assertEquals("first divider should be 1", 1, (int) dividers.get(0));
   assertEquals(String.format("first divider should be %d", primeNumber), primeNumber, dividers.get(1));
  });
}
like image 33
Gabriel Deliu Avatar answered Sep 19 '22 12:09

Gabriel Deliu