@Test
public void shouldInsertPetIntoDatabaseAndGenerateId() {
Owner owner6 = this.clinicService.findOwnerById(6);
int found = owner6.getPets().size();
Pet pet = new Pet();
pet.setName("bowser");
Collection<PetType> types = this.clinicService.findPetTypes();
pet.setType(EntityUtils.getById(types, PetType.class, 2));
pet.setBirthDate(new DateTime());
owner6.addPet(pet);
assertThat(owner6.getPets().size()).isEqualTo(found + 1);
this.clinicService.savePet(pet);
this.clinicService.saveOwner(owner6);
owner6 = this.clinicService.findOwnerById(6);
assertThat(owner6.getPets().size()).isEqualTo(found + 1);
// checks that id has been generated
assertThat(pet.getId()).isNotNull();
}
Beispiel von github.com/spring-projects/spring-petclinic
Regel 1: "Ein Test wird rot und niemand weiß warum. Selbst bei intensiver Betrachtung ist noch nicht einmal klar, was der Test eigentlich sicherstellen sollte."
Scenario: Pets can be assigned to pet owners
Given an existing pet owner
And a dog named "bowser"
When assigning the pet to the pet owner
Then the pet owner owns an additional pet
Feature: Finding Owners
Scenario: Owners can be found by last name
Given an owner with last name "Müller"
When searching for "Müller"
Then exactly the given owner is found
public class CustomerStepdefs {
@Given("an owner with last name (.*)")
public void anOwnerWithLastName(String lastName) { ... }
@When("searching for (.*)")
public void searchingFor(String lastName) { ... }
@Then("exactly the given owner is found")
public void exactlyTheGivenOwnerIsFound() { ... }
}
import org.junit.Test;
import com.tngtech.jgiven.junit.SimpleScenarioTest;
public class FindOwnerTest extends SimpleScenarioTest<StepDefs> {
@Test
public void owners_can_be_found_by_last_name() {
given().an_owner_with_last_name("Müller");
when().searching_for("Müller");
then().exactly_the_given_owner_is_found();
}
}
Scenario: owners can be found by last name
Given an owner with last name "Müller"
When searching for "Müller"
Then exactly the given owner is found
import com.tngtech.jgiven.(junit|testng).ScenarioTest;
public class SomeScenarioTest extends ScenarioTest<...> {
}
*Oder SimpleScenarioTest
import com.tngtech.jgiven.junit.ScenarioTest;
public class SomeScenarioTest
extends ScenarioTest<MyGivenStage, MyWhenStage, MyThenStage> {
}
import org.junit.Test;
import com.tngtech.jgiven.junit.ScenarioTest;
public class SomeScenarioTest
extends ScenarioTest<MyGivenStage, MyWhenStage, MyThenStage> {
@Test
public void my_first_scenario() { ... }
}
import org.junit.Test;
import com.tngtech.jgiven.junit.ScenarioTest;
public class SomeScenarioTest
extends ScenarioTest<MyGivenStage, MyWhenStage, MyThenStage> {
@Test
public void my_first_scenario() {
given().some_initial_state();
when().some_action();
then().the_result_is_correct();
}
}
import com.tngtech.jgiven.Stage;
public class MyGivenStage extends Stage<MyGivenStage> {
int state;
public MyGivenStage some_initial_state() {
state = 42;
return this;
}
}
public class MyGivenStage extends Stage<MyGivenStage> {
@ProvidedScenarioState
int state;
public MyGivenStage some_initial_state() {
state = 42;
return self();
}
}
public class MyWhenStage extends Stage<MyWhenStage> {
@ExpectedScenarioState
int state;
@ProvidedScenarioState
int result;
public MyWhenStage some_action() {
result = state * state;
}
}
given().a_customer_with_name( "John" );
Given a customer with name John
Given there are 5 coffees left
given().there_are_$_coffees_left( 5 );
@Test
@DataProvider({
"1, 0",
"3, 2",
"5, 4"})
public void the_stock_is_reduced_when_a_book_is_ordered( int initial,
int left ) {
given().a_customer()
.and().a_book()
.with().$_items_on_stock( initial );
when().the_customer_orders_the_book();
then().there_are_$_items_left_on_stock( left );
}
Verwendet den DataProviderRunner (github.com/TNG/junit-dataprovider).
Scenario: the stock is reduced when a book is ordered
Given a customer
And a book
With <initial> items on stock
When the customer orders the book
Then there are <left> items left on stock
Cases:
| # | initial | left | Status |
+---+---------+------+---------+
| 1 | 1 | 0 | Success |
| 2 | 3 | 2 | Success |
| 3 | 5 | 4 | Success |
@Test
@DataProvider({"1", "3", "5"})
public void the_stock_is_reduced_when_a_book_is_ordered( int initial ) {
given().a_customer()
.and().a_book()
.with().$_items_on_stock( initial );
when().the_customer_orders_the_book();
then().there_are_$_items_left_on_stock( initial - 1 );
}
Scenario: the stock is reduced when a book is ordered
Given a customer
And a book
With <initial> items on stock
When the customer orders the book
Then there are <numberOfItems> items left on stock
Cases:
| # | initial | numberOfItems | Status |
+---+---------+---------------+---------+
| 1 | 1 | 0 | Success |
| 2 | 3 | 2 | Success |
| 3 | 5 | 4 | Success |
@Test
@DataProvider({ "3, 2, true",
"0, 0, false" })
public void the_stock_is_only_reduced_when_possible(
int initial, int left, boolean orderExists) {
given().a_customer()
.and().a_book()
.with().$_items_on_stock( initial );
when().the_customer_orders_the_book();
if ( orderExists ) {
then().a_corresponding_order_exists_for_the_customer();
} else {
then().no_corresponding_order_exists_for_the_customer();
}
}
Scenario: the stock is only reduced when possible
Case 1: initial = 3, left = 2, orderExists = true
Given a customer
And a book
With 3 items on stock
When the customer orders the book
Then there are 2 items left on stock
And a corresponding order exists for the customer
Case 2: initial = 0, left = 0, orderExists = false
Given a customer
And a book
With 0 items on stock
When the customer orders the book
Then there are 0 items left on stock
And no corresponding order exists for the customer
@Format( value = BooleanFormatter.class, args = { "on", "off" } )
@Retention( RetentionPolicy.RUNTIME )
@interface OnOff {}
public SELF the_machine_is_$( @OnOff boolean onOrOff ) { ... }
given().the_machine_is_$( false );
Given the machine is off
SELF the_following_books_are_on_stock( @Table String[][] stockTable ) {
...
}
@Test
public void ordering_a_book_reduces_the_stock() {
given().the_following_books_on_stock(new String[][]{
{"id", "name", "author", "stock"},
{"1", "The Hitchhiker's Guide to the Galaxy", "Douglas Adams", "5"},
{"2", "Lord of the Rings", "John Tolkien", "3"},
});
when().a_customer_orders_book("1");
then().the_stock_looks_as_follows(new String[][]{
{"id", "name", "author", "stock"},
{"1", "The Hitchhiker's Guide to the Galaxy", "Douglas Adams", "4"},
{"2", "Lord of the Rings", "John Tolkien", "3"},
});
}
Scenario: ordering a book reduces the stock
Given the following books on stock
| id | name | author | stock |
+----+--------------------------------------+---------------+-------+
| 1 | The Hitchhiker's Guide to the Galaxy | Douglas Adams | 5 |
| 2 | Lord of the Rings | John Tolkien | 3 |
When a customer orders book 1
Then the stock looks as follows
| id | name | author | stock |
+----+--------------------------------------+---------------+-------+
| 1 | The Hitchhiker's Guide to the Galaxy | Douglas Adams | 4 |
| 2 | Lord of the Rings | John Tolkien | 3 |
SELF the_following_books_are_on_stock( @Table List<BookOnStock> books) {
...
}
SELF the_following_book(
@Table(includeFields = {"name", "author", "priceInEurCents"},
header = VERTICAL) Book book) {
...
}
public class GivenSteps extends Stage<GivenSteps> {
@ProvidedScenarioState
File temporaryFolder;
@BeforeScenario
void setupTemporaryFolder() {
temporaryFolder = ...
}
@AfterScenario
void deleteTemporaryFolder() {
temporaryFolder.delete();
}
}
public class TemporaryFolderRule {
File temporaryFolder;
public void before() {
temporaryFolder = ...
}
public void after() {
temporaryFolder.delete();
}
}
public class GivenSteps extends Stage<GivenSteps> {
@ScenarioRule
TemporaryFolderRule rule = new TemporaryFolderRule();
}
public class GivenCustomer extends Stage<GivenSteps> {
CustomerBuilder builder;
@ProvidedScenarioState
Customer customer;
public void a_customer() {
builder = new CustomerBuilder();
}
public void with_age(int age) {
builder.withAge(age);
}
@AfterStage
void buildCustomer() {
customer = builder.build();
}
}
@Test @FeatureEmail
void the_customer_gets_an_email_when_ordering_a_book() {
...
}
@Test @Story( "ABC-123" )
void the_customer_gets_an_email_when_ordering_a_book() { ... }
@Hidden
public SELF doSomethingTechnical() { ... }
@ExtendedDescription("The Hitchhiker's Guide to the Galaxy, "
+ "by default the book is not on stock" )
public SELF a_book() { ... }
public class Html5ReportStage {
@ExpectedScenarioState
protected CurrentStep currentStep; // provided by JGiven
protected void takeScreenshot() {
String base64 = ( (TakesScreenshot) webDriver )
.getScreenshotAs( OutputType.BASE64 );
currentStep.addAttachment(
Attachment.fromBase64( base64, MediaType.PNG )
.withTitle( "Screenshot" ) );
}
}