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:
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
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.
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.
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.
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.
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).
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));
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With