From 75859f564a1087ccccd1ac941ad04a5f7e2ded3e Mon Sep 17 00:00:00 2001 From: John Smart Date: Wed, 17 Aug 2016 00:10:40 +0100 Subject: [PATCH 01/13] Kata sample solution --- README.md | 33 ++-- pom.xml | 10 + .../tutorials/vetclinic/Breed.java | 5 + .../serenitylabs/tutorials/vetclinic/Pet.java | 57 ++++++ .../collections/katas/APetHotel.java | 50 +++++ .../katas/BookingAcknowledgement.java | 7 + .../katas/BookingConfirmation.java | 19 ++ .../collections/katas/BookingResponse.java | 32 +++ .../collections/katas/Calculator.java | 9 + .../collections/katas/CheckInStrategy.java | 7 + .../katas/ConfirmBookingStrategy.java | 19 ++ .../vetclinic/collections/katas/PetHotel.java | 48 +++++ .../katas/PlacedOnWaitingList.java | 19 ++ .../katas/SpecialisedPetHotel.java | 19 ++ .../katas/WaitingListStrategy.java | 20 ++ .../WhenWorkingWithAListOfPetNames.java | 98 +++++++++ .../exercises/WhenWorkingWithAListOfPets.java | 25 +++ .../exercises/WhenWorkingWithAPetMap.java | 93 +++++++++ .../exercises/WhenWorkingWithAPetQueue.java | 41 ++++ .../exercises/WhenWorkingWithASetOfPets.java | 47 +++++ .../WhenWorkingWithAStackOfPets.java | 43 ++++ .../vetclinic/collections/katas/README.md | 79 ++++++++ .../katas/WhenBookingPetsIntoAPetHotel.java | 187 ++++++++++++++++++ 23 files changed, 949 insertions(+), 18 deletions(-) create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/Breed.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/Pet.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java create mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md create mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java diff --git a/README.md b/README.md index cba035dc..1e296357 100644 --- a/README.md +++ b/README.md @@ -2,29 +2,26 @@ This project is used as the basis of a number of tutorials and exercises, as part of the *Professional Java Development and Test Automation Skills* program (see http://johnfergusonsmart.com/products). Each tutorial explores a different technique or practice essential to modern Java developers or Engineers in Test. -These tutorials are designed to be used as the basis of small coding exercises (similar to very short coding katas) that you can learn and practice until you are familiar with a particular technique. The approach is outlined here: +These exercises are designed to help you become familiar with using collections in Java. The first ones are designed to help you learn the Java Collections APIs, whereas the second -![Learning from the tutorials](src/documentation/images/tutorial-process.png) +## Working with collections -1. Clone this repository and check out the starting point for the tutorial you want to do. -2. Watch the tutorial and follow along on your own machine. -3. Redo the tutorial following the step-by-step instructions given in the tutorial's README file. -4. Redo the exercise without the instructions. +### Step 1 - Implement the tests in the `WhenWorkingWithAListOfPetNames` class. -## The problem domain +### Step 2 - Implement the tests in the `WhenWorkingWithAListOfPets` class. -The domain is a simple one. We are writing an application for a Vet clinic, where you can take your pets to be treated when they are sick. At the vet clinic, we need to be able to register new animals when they arrive for treatment. +### Step 3 - Implement all the tests in the `WhenWorkingWithASetOfPets` class. + +### Step 4 - Implement all the tests in the `WhenWorkingWithAPetMap` class. + +### Step 5 - Implement all the tests in the `WhenWorkingWithAPetQueue` class. + +### Step 6 - Implement all the tests in the `WhenWorkingWithAStackOfPets` class. + +## Applying what you have learned + +### Kata 1 - Calculating sums -## Starting a tutorial -Each tutorial has two main branches, one for the starting point for the tutorial, and one for a sample solution. The format for the branch names uses a simple naming convention to identify the starting point and the sample solutions for each tutorial. For example, to start tutorial 1, check out the `start` branch like this: -``` -$ git checkout tutorial-1/start -``` -And to see the solution for tutorial 1, use the solution branch: -``` -$ git checkout tutorial-1/solution -``` -Go to the tutorial branch to see the step-by-step instructions for that tutorial. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8e537898..d596e497 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,16 @@ 3.1.0 test + + org.hamcrest + hamcrest-all + 1.3 + + + com.google.guava + guava + 19.0 + diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/Breed.java b/src/main/java/serenitylabs/tutorials/vetclinic/Breed.java new file mode 100644 index 00000000..b03defc1 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/Breed.java @@ -0,0 +1,5 @@ +package serenitylabs.tutorials.vetclinic; + +public enum Breed { + Cat, Dog, Rabbit, Fish, Parrot +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java b/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java new file mode 100644 index 00000000..8d4d40fa --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java @@ -0,0 +1,57 @@ +package serenitylabs.tutorials.vetclinic; + +import com.google.common.base.Objects; + +public class Pet { + private final String name; + private final Breed breed; + + public Pet(String name, Breed breed) { + this.name = name; + this.breed = breed; + } + + public String getName() { + return name; + } + + public Breed getBreed() { + return breed; + } + + public static PetBuilder dog() { return new PetBuilder(Breed.Dog);} + public static PetBuilder cat() { return new PetBuilder(Breed.Cat);} + public static PetBuilder rabbit() { return new PetBuilder(Breed.Rabbit);} + public static PetBuilder parrot() { return new PetBuilder(Breed.Parrot);} + public static PetBuilder fish() { return new PetBuilder(Breed.Fish);} + + public static class PetBuilder { + private final Breed breed; + + public PetBuilder(Breed breed) { + this.breed = breed; + } + + public Pet named(String name) { + return new Pet(name, breed); + } + } + + @Override + public String toString() { + return "a " + breed + " called " + name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Pet pet = (Pet) o; + return Objects.equal(name, pet.name) && breed == pet.breed; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, breed); + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java new file mode 100644 index 00000000..a37af38b --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java @@ -0,0 +1,50 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import com.google.common.collect.ImmutableList; +import serenitylabs.tutorials.vetclinic.Breed; +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.List; +import java.util.Random; + +/** + * A utility class to generate pet hotels with pets already booked + */ +public class APetHotel { + public static PetAdder with(int petCount) { + return new PetAdder(petCount); + } + + public static class PetAdder { + private final int petCount; + + public PetAdder(int petCount) { + + this.petCount = petCount; + } + + public PetHotel petsCheckedIn() { + PetHotel hotel = new PetHotel(); + for(int count = 0; count < petCount; count++) { + hotel.checkIn(somePet(count)); + } + return hotel; + } + + private Pet somePet(int petCount) { + return new Pet(someName(petCount), someBreed()); + } + + private final static Random random = new Random(); + + private Breed someBreed() { + return Breed.values()[ random.nextInt(Breed.values().length) ]; + } + + private final static List PET_NAMES = ImmutableList.of("Fido","Felix","Rover","Spot"); + + private String someName(int petCount) { + return PET_NAMES.get(random.nextInt(PET_NAMES.size())) + " " + petCount; + } + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java new file mode 100644 index 00000000..89fbcf62 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java @@ -0,0 +1,7 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +public interface BookingAcknowledgement { + boolean isConfirmed(); + + boolean isOnWaitingList(); +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java new file mode 100644 index 00000000..054a17a3 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java @@ -0,0 +1,19 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +public class BookingConfirmation extends BookingResponse { + public BookingConfirmation(int number, Pet pet) { + super(number, pet); + } + + @Override + public boolean isConfirmed() { + return true; + } + + @Override + public boolean isOnWaitingList() { + return false; + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java new file mode 100644 index 00000000..4226fe34 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java @@ -0,0 +1,32 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class BookingResponse implements BookingAcknowledgement { + private static AtomicInteger bookingNumberCounter = new AtomicInteger(); + private final int number; + private final Pet pet; + + public BookingResponse(int number, Pet pet) { + this.number = number; + this.pet = pet; + } + + public static BookingResponse confirmedFor(Pet pet) { + return new BookingConfirmation(bookingNumberCounter.incrementAndGet(), pet); + } + + public static BookingResponse waitingListFor(Pet pet) { + return new PlacedOnWaitingList(bookingNumberCounter.incrementAndGet(), pet); + } + + public Pet getPet() { + return pet; + } + + public int getNumber() { + return number; + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java new file mode 100644 index 00000000..7a56cf53 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java @@ -0,0 +1,9 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +public class Calculator { + protected int field; + + public Integer calculate(String expression) { + return 0; + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java new file mode 100644 index 00000000..b82412ed --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java @@ -0,0 +1,7 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +public interface CheckInStrategy { + BookingResponse attemptToCheckIn(Pet pet); +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java new file mode 100644 index 00000000..04675e07 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java @@ -0,0 +1,19 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.Collection; + +public class ConfirmBookingStrategy implements CheckInStrategy { + private final Collection pets; + + public ConfirmBookingStrategy(Collection pets) { + this.pets = pets; + } + + @Override + public BookingResponse attemptToCheckIn(Pet pet) { + pets.add(pet); + return BookingResponse.confirmedFor(pet); + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java new file mode 100644 index 00000000..5f2ab8f6 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java @@ -0,0 +1,48 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.*; + +import static java.util.Comparator.comparing; + +public class PetHotel { + + public static final int MAXIMUM_PETS = 20; + + private Collection pets = new TreeSet<>(comparing(Pet::getName)); + private Queue waitingList = new LinkedList<>(); + + public List getPets() { + return new ArrayList<>(pets); + } + + private enum HotelAvailability { Available, Full} + + private static final Map CHECK_IN_STRATEGY = new HashMap<>(); + { + CHECK_IN_STRATEGY.put(HotelAvailability.Available, new ConfirmBookingStrategy(pets)); + CHECK_IN_STRATEGY.put(HotelAvailability.Full, new WaitingListStrategy(waitingList)); + } + + private HotelAvailability currentAvailability() { + return (pets.size() >= MAXIMUM_PETS) ? HotelAvailability.Full : HotelAvailability.Available; + } + + public BookingResponse checkIn(Pet pet) { + CheckInStrategy checkInStrategy = CHECK_IN_STRATEGY.get(currentAvailability()); + return checkInStrategy.attemptToCheckIn(pet); + } + + public Collection getWaitingList() { + return new ArrayList<>(waitingList); + } + + public void checkOut(Pet pet) { + pets.remove(pet); + + if (!waitingList.isEmpty()) { + checkIn(waitingList.poll()); + } + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java new file mode 100644 index 00000000..26007683 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java @@ -0,0 +1,19 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +public class PlacedOnWaitingList extends BookingResponse { + public PlacedOnWaitingList(int number, Pet pet) { + super(number, pet); + } + + @Override + public boolean isConfirmed() { + return false; + } + + @Override + public boolean isOnWaitingList() { + return true; + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java new file mode 100644 index 00000000..ea9d08a1 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java @@ -0,0 +1,19 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import java.util.ArrayList; +import java.util.List; + +public class SpecialisedPetHotel { + + List pets = new ArrayList<>(); + + public void checkIn(T pet) { + pets.add(pet); + } + + public List getPets() { + return new ArrayList<>(pets); + } + + +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java new file mode 100644 index 00000000..0ea45147 --- /dev/null +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java @@ -0,0 +1,20 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.Collection; + +public class WaitingListStrategy implements CheckInStrategy { + private final Collection relevantPets; + + public WaitingListStrategy(Collection pets) { + this.relevantPets = pets; + } + + @Override + public BookingResponse attemptToCheckIn(Pet pet) { + relevantPets.add(pet); + return BookingResponse.waitingListFor(pet); + } + +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java new file mode 100644 index 00000000..80f0b910 --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java @@ -0,0 +1,98 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import com.google.common.collect.Lists; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.junit.Assert.assertThat; + +public class WhenWorkingWithAListOfPetNames { + + @Test + public void should_add_Fido_to_the_list_of_pets() { + List names = Lists.newArrayList(); + + // TODO + names.add("Fido"); + + assertThat(names, hasItems("Fido")); + } + + @Test + public void should_remove_Fido_from_the_list_of_pets() { + List names = Lists.newArrayList("Felix","Fido","Spot"); + // TODO + names.remove("Fido"); + + assertThat(names, hasItems("Felix","Spot")); + } + + @Test + public void should_remove_the_first_pet_from_the_list_of_pets() { + List names = Lists.newArrayList("Felix","Fido","Spot"); + + // TODO + names.remove(0); + + assertThat(names, hasItems("Fido","Spot")); + } + + @Test + public void should_make_a_list_of_cats_and_dogs() { + List cats = Lists.newArrayList("Felix","Spot"); + List dogs = Lists.newArrayList("Fido","Rover"); + + // TODO + List catsAndDogs = new ArrayList(cats); + catsAndDogs.addAll(dogs); + + assertThat(catsAndDogs, hasItems("Felix","Spot","Fido","Rover")); + } + + @Test + public void should_put_the_dogs_among_the_cats() { + List cats = Lists.newArrayList("Felix","Spot"); + List dogs = Lists.newArrayList("Fido","Rover"); + + // TODO + List catsAndDogs = new ArrayList(cats); + catsAndDogs.addAll(1,dogs); + + assertThat(catsAndDogs, hasItems("Felix","Fido","Rover","Spot")); + } + + @Test + public void should_organise_pets_in_alphabetical_order() { + List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); + + // TODO + pets.sort(Comparator.naturalOrder()); + + assertThat(pets, hasItems("Felix","Fido","Rover","Spot")); + } + + @Test + public void should_organise_pets_in_reverse_alphabetical_order() { + List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); + + // TODO + pets.sort(Comparator.reverseOrder()); + + assertThat(pets, hasItems("Spot","Rover","Fido","Felix")); + } + + @Test + public void should_organise_pets_by_name_length() { + List pets = Lists.newArrayList("Felix","Alfred","Spot"); + + // TODO + pets.sort(Comparator.comparing(String::length)); + + assertThat(pets, hasItems("Spot","Felix","Alfred")); + } + +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java new file mode 100644 index 00000000..14d0090a --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java @@ -0,0 +1,25 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; + +public class WhenWorkingWithAListOfPets { + + @Test + public void should_store_a_list_of_pets() { + + List pets = new ArrayList<>(); + + pets.add(Pet.cat().named("Felix")); + pets.add(Pet.dog().named("Fido")); + + // TODO: Implement the equals and hashcode methods in the Pet class to make this work + assertThat(pets, hasItem(Pet.dog().named("Fido"))); + } +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java new file mode 100644 index 00000000..3bc14d3a --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java @@ -0,0 +1,93 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Breed; +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.*; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class WhenWorkingWithAPetMap { + + @Test + public void pets_can_be_found_by_their_name() { + Map pets = new HashMap<>(); + + Pet fido = Pet.dog().named("Fido"); + + pets.put("Fido", fido); + + // TODO + assertThat(pets.get("Fido"), equalTo(fido)); + } + + @Test + public void should_be_able_to_get_a_default_value_if_no_matching_key_is_present() { + Map pets = new HashMap<>(); + + Pet fido = Pet.dog().named("Fido"); + Pet stray = Pet.dog().named("Stray"); + + pets.put("Fido", fido); + pets.put("Stray", stray); + + Pet retrievedPet = pets.getOrDefault("Rover", stray); + + // TODO + assertThat(retrievedPet, equalTo(stray)); + } + + @Test + public void the_map_keys_should_be_the_pet_names() { + Map pets = new HashMap<>(); + + Pet fido = Pet.dog().named("Fido"); + Pet felix = Pet.cat().named("Felix"); + + pets.put("Fido", fido); + pets.put("Felix", felix); + + // TODO + assertThat(pets.keySet(), containsInAnyOrder("Fido","Felix")); + } + + @Test + public void the_map_should_store_pets_in_alphabetical_order() { + // TODO: Instantiate the correct type of Map + NavigableMap pets = new TreeMap<>(); + + pets.put("Rover", Pet.dog().named("Rover")); + pets.put("Felix", Pet.cat().named("Felix")); + pets.put("Spot", Pet.cat().named("Spot")); + + assertThat(pets.keySet(), contains("Felix","Rover","Spot")); + } + + @Test + public void the_map_should_store_pets_in_the_order_they_where_added() { + // TODO: Instantiate the correct type of Map + Map pets = new LinkedHashMap<>(); + + pets.put("Spot", Pet.cat().named("Spot")); + pets.put("Rover", Pet.dog().named("Rover")); + pets.put("Felix", Pet.cat().named("Felix")); + pets.put("Fido", Pet.cat().named("Fido")); + + assertThat(pets.keySet(), contains("Spot", "Rover","Felix", "Fido")); + } + + @Test + public void the_map_should_store_pet_leaders_by_breed() { + // TODO: Create an EnumMap to define a pet leader for each breed + EnumMap petLeaders = new EnumMap<>(Breed.class); + + petLeaders.put(Breed.Cat, Pet.cat().named("Felix")); + petLeaders.put(Breed.Dog, Pet.dog().named("Lassie")); + petLeaders.put(Breed.Rabbit, Pet.cat().named("Hazel")); + + assertThat(petLeaders.get(Breed.Dog).getName(), equalTo("Lassie")); + } + +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java new file mode 100644 index 00000000..c4007529 --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java @@ -0,0 +1,41 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.LinkedList; +import java.util.Queue; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +public class WhenWorkingWithAPetQueue { + + @Test + public void should_add_Fido_to_the_end_of_the_queue() { + Queue waitingList = new LinkedList<>(); + + waitingList.add(Pet.cat().named("Felix")); + waitingList.add(Pet.dog().named("Fido")); + + Pet nextInLine = waitingList.poll(); + + // TODO + assertThat(nextInLine.getName(), equalTo("Felix")); + } + + @Test + public void should_see_who_is_at_the_top_of_the_queue_without_removing_it() { + Queue waitingList = new LinkedList<>(); + + waitingList.add(Pet.cat().named("Felix")); + waitingList.add(Pet.dog().named("Fido")); + + Pet nextInLine = waitingList.peek(); + + // TODO + assertThat(nextInLine.getName(), equalTo("Felix")); + } + + +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java new file mode 100644 index 00000000..b13215b4 --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java @@ -0,0 +1,47 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import com.google.common.collect.Sets; +import org.junit.Test; + +import java.util.Set; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertThat; + +public class WhenWorkingWithASetOfPets { + + @Test + public void should_add_Fido_to_the_set_of_pets() { + Set names = Sets.newHashSet(); + + // TODO + names.add("Fido"); + + assertThat(names, contains("Fido")); + } + + @Test + public void a_set_of_pets_should_not_contain_duplicates() { + Set names = Sets.newHashSet(); + + names.add("Fido"); + names.add("Felix"); + names.add("Fido"); + + // TODO + assertThat(names, containsInAnyOrder("Fido","Felix")); + } + + @Test + public void adding_several_pets() { + Set names = Sets.newHashSet("Fido","Felix"); + + names.addAll(Sets.newHashSet("Felix","Spot")); + + // TODO + assertThat(names, containsInAnyOrder("Fido","Felix","Spot")); + } + + +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java new file mode 100644 index 00000000..9cad2703 --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java @@ -0,0 +1,43 @@ +package serenitylabs.tutorials.vetclinic.collections.exercises; + +import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.Deque; +import java.util.LinkedList; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class WhenWorkingWithAStackOfPets { + + @Test + public void should_store_pets_in_a_stack() { + + Deque pets = new LinkedList<>(); + + pets.push(Pet.cat().named("Felix")); + pets.push(Pet.dog().named("Fido")); + + // TODO: Retrieve the last pet put on the list + Pet lastPet = pets.pop(); + + assertThat(lastPet.getName(),equalTo("Fido")); + assertThat(pets.size(), equalTo(1)); + } + + @Test + public void should_see_the_next_item_in_a_stack() { + + Deque pets = new LinkedList<>(); + + pets.push(Pet.cat().named("Felix")); + pets.push(Pet.dog().named("Fido")); + + // TODO: Retrieve the last pet put on the list + Pet lastPet = pets.peek(); + + assertThat(lastPet.getName(),equalTo("Fido")); + assertThat(pets.size(), equalTo(2)); + } +} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md new file mode 100644 index 00000000..ca7b0781 --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md @@ -0,0 +1,79 @@ +# Collections Katas + +## Booking pets into a pet hotel + +The aim of this kata is to implement a Pet hotel with the following requirements: + + - Pet owners should be able to check their pet into the hotel + - Pet owners should receive a confirmation that their pet has been successfully checked in + - The hotel owner should be able to list all of the pets in the hotel in alphabetical order + - The hotel should have a maximum capacity of 20 animals. + - When a pet owner checks in their pet and the hotel is full, they should receive a confirmation that their pet has been placed on a waiting list. + - When a pet checks out of the hotel, the first animal on the waiting list should be automatically checked in. + +When you first do the exercise, implement the features by progressively making all of the acceptance tests in the pass, one after the other. The `WhenBookingPetsIntoAPetHotel` test class contains a sequence of unit tests for each feature to be implemented. The last line in each test is a Hamcrest assertion that is commented out. Uncomment the assertion, then follow the steps below to implement each feature and make the tests pass. + +Once you have finished, repeat the exercise, but first deleting all of the tests and then rewriting them using a TDD approach (i.e. Write a failing test for a feature, make it pass, refactor the code, move to the next feature). + +## The Steps + +# Step 1 - Check a pet into the hotel (part 1) +_Test case:_ `the_hotel_should_initially_have_no_pets_booked()` + +Create a new class `PetHotel` and give it a method `getPets()` that returns null. Make sure the test fails, then get the `getPets()` method to return an empty collection of `Pet` instances. + +# Step 2 - Check a pet into the hotel (part 2) + +_Test case:_ `should_be_able_to_check_a_pet_into_the_hotel()` + +Add a method `checkIn()` to the `PetHotel` class, that takes a `Pet` as a parameter, and demonstrate that when you check a pet into the hotel, it can be retrieved via the `getPets()` method. Implement the list of pets in the `PetHotel` class as an `ArrayList`. + +# Step 3 - Check a pet into the hotel (part 3) + +_Test case:_ `should_be_able_to_check_in_several_pets()` + +Demonstrate that you can check several pets into the hotel, and that they all can be retrieved via the `getPets()` method. + +# Step 4 - Check a pet into the hotel (part 4) + +_Test case:_ `should_not_be_able_to_check_in_the_same_pet_twice()` + +Demonstrate that if you check in the same pet twice, it should have no effect on the current pet list. Refactor the pet list field to use a `TreeMap` instead of an `ArrayList`. + +# Step 5 - Pet owners should receive a confirmation that their pet has been successfully checked in + +_Test case:_ `should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet()` + +Demonstrate that when an owner checks in a pet, they receive a `BookingResponse` object which contains a reference to the pet, a booking number, and a method `isConfirmed()` that returns `true`. + + +# Step 6 - The hotel owner should be able to list all of the pets in the hotel in alphabetical order + +_Test case:_ `should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order()` + +Make this work by refactoring the pet list field to use a `TreeMap` with a Java 8 comparator. + +# Step 7 - The hotel should have a maximum capacity of 20 animals. + +_Test case:_ `should_not_be_able_to_check_in_pets_beyond_hotel_capacity()` + +This test should check that when an owner checks in a pet when the hotel is full, the pet is not added to the pet list. + +# Step 8 + +_Test case:_ `should_notify_owner_that_the_hotel_is_full()` + +Ensure that when an owner checks in a pet to a full hotel, the hotel returns a `Response` that indicates that the booking is not confirmed (`isConfirmed()` returns false), and that the pet has been placed on a waiting list (via a new method, 'isOnWaitingList()` is true). + +# Step 9 + +_Test case:_ `pets_on_the_waiting_list_should_be_added_to_the_hotel_when_a_place_is_freed()` + +Ensure that when a pet checks out of the hotel, the first pet on the waiting list is automatically checked in. + +# Step 10 + +_Test case:_ `pets_on_the_waiting_list_should_be_admitted_on_a_first_come_first_served_basis()` + +Ensure that pets on the waiting list are checked in on a first-come-first-served basis. + diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java new file mode 100644 index 00000000..db45270c --- /dev/null +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java @@ -0,0 +1,187 @@ +package serenitylabs.tutorials.vetclinic.collections.katas; + +import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Pet; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class WhenBookingPetsIntoAPetHotel { + + + @Test + public void the_hotel_should_initially_have_no_pets_booked() { + // GIVEN + PetHotel hotel = new PetHotel(); + + // THEN + assertThat(hotel.getPets(), hasSize(0)); + } + + @Test + public void should_be_able_to_check_a_pet_into_the_hotel() throws Exception { + // GIVEN + PetHotel hotel = new PetHotel(); + Pet fido = Pet.dog().named("Fido"); + + // WHEN + hotel.checkIn(fido); + + // THEN + assertThat(hotel.getPets(), hasItem(fido)); + } + + @Test + public void should_be_able_to_check_in_several_pets() throws Exception { + // GIVEN + PetHotel hotel = new PetHotel(); + Pet fido = Pet.dog().named("Fido"); + Pet felix = Pet.cat().named("Felix"); + + // WHEN + hotel.checkIn(fido); + hotel.checkIn(felix); + + // THEN + assertThat(hotel.getPets(), hasItems(fido,felix)); + } + + @Test + public void should_not_be_able_to_check_in_the_same_pet_twice() throws Exception { + // GIVEN + PetHotel hotel = new PetHotel(); + Pet fido = Pet.dog().named("Fido"); + Pet felix = Pet.cat().named("Felix"); + + // AND + hotel.checkIn(fido); + hotel.checkIn(felix); + + // WHEN + hotel.checkIn(fido); + + // THEN + assertThat(hotel.getPets(), containsInAnyOrder(fido, felix)); + } + + @Test + public void should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order() throws Exception { + // GIVEN + PetHotel hotel = new PetHotel(); + Pet hazel = Pet.rabbit().named("Hazel"); + Pet rover = Pet.dog().named("Rover"); + Pet felix = Pet.cat().named("Felix"); + + // WHEN + hotel.checkIn(hazel); + hotel.checkIn(rover); + hotel.checkIn(felix); + + // THEN + assertThat(hotel.getPets(), contains(felix, hazel, rover)); + } + + @Test + public void should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet() throws Exception { + // GIVEN + PetHotel hotel = new PetHotel(); + Pet fido = Pet.dog().named("Fido"); + + // WHEN + BookingResponse confirmation = hotel.checkIn(fido); + + // THEN + assertThat(confirmation.getNumber(), greaterThan(0)); + assertThat(confirmation.getPet(), equalTo(fido)); + assertThat(confirmation.isConfirmed(), equalTo(true)); + } + + @Test + public void should_not_be_able_to_check_in_pets_beyond_hotel_capacity() throws Exception { + // GIVEN + PetHotel hotel = APetHotel.with(PetHotel.MAXIMUM_PETS).petsCheckedIn(); + + // WHEN + hotel.checkIn(Pet.dog().named("Lassie")); + + assertThat(hotel.getPets(), hasSize(20)); + } + + /** + * + * Refactor checkIn method to return a BookingAcknowledgement interface, which has two methods: isConfirmed() + * and isOnWaitingList(). + * You will need to complete the APetHotel helper class used in the Given. + */ + @Test + public void should_notify_owner_that_the_hotel_is_full() throws Exception { + // GIVEN + PetHotel hotel = APetHotel.with(20).petsCheckedIn(); + + // WHEN + BookingResponse response = hotel.checkIn(Pet.dog().named("Lassie")); + + // THEN + assertThat(response.isConfirmed(), is(false)); + assertThat(response.isOnWaitingList(), is(true)); + + } + + + @Test + public void should_place_pets_on_a_waiting_list_when_the_hotel_is_full() throws Exception { + // GIVEN + PetHotel hotel = APetHotel.with(20).petsCheckedIn(); + Pet lassie = Pet.dog().named("Lassie"); + + // WHEN + hotel.checkIn(lassie); + + // THEN + assertThat(hotel.getWaitingList(), hasItem(lassie)); + } + + + @Test + public void pets_on_the_waiting_list_should_be_added_to_the_hotel_when_a_place_is_freed() throws Exception { + // GIVEN + PetHotel hotel = APetHotel.with(19).petsCheckedIn(); + Pet fido = Pet.dog().named("Fido"); + Pet lassie = Pet.dog().named("Lassie"); + + hotel.checkIn(fido); + + // WHEN + hotel.checkIn(lassie); + // AND + hotel.checkOut(fido); + + // THEN + assertThat(hotel.getPets(), hasItem(lassie)); + } + + + @Test + public void pets_on_the_waiting_list_should_be_admitted_on_a_first_come_first_served_basis() throws Exception { + // GIVEN + PetHotel hotel = APetHotel.with(19).petsCheckedIn(); + Pet felix = Pet.cat().named("Felix"); + + Pet fido = Pet.dog().named("Fido"); + Pet lassie = Pet.dog().named("Lassie"); + + + hotel.checkIn(felix); + + // WHEN + hotel.checkIn(fido); + hotel.checkIn(lassie); + // AND + hotel.checkOut(felix); + + // THEN + assertThat(hotel.getPets(), hasItem(fido)); + assertThat(hotel.getPets(), not(hasItem(lassie))); + } + +} From 56695d1a82801dc87e2a6bd808199cf46d5ded7f Mon Sep 17 00:00:00 2001 From: John Smart Date: Wed, 17 Aug 2016 00:25:47 +0100 Subject: [PATCH 02/13] initial state --- .../collections/katas/APetHotel.java | 15 +- .../katas/BookingAcknowledgement.java | 7 - .../katas/BookingConfirmation.java | 19 --- .../collections/katas/BookingResponse.java | 32 ----- .../collections/katas/Calculator.java | 9 -- .../collections/katas/CheckInStrategy.java | 7 - .../katas/ConfirmBookingStrategy.java | 19 --- .../vetclinic/collections/katas/PetHotel.java | 48 ------- .../katas/PlacedOnWaitingList.java | 19 --- .../katas/SpecialisedPetHotel.java | 19 --- .../katas/WaitingListStrategy.java | 20 --- .../WhenWorkingWithAListOfPetNames.java | 12 +- .../exercises/WhenWorkingWithAPetMap.java | 9 +- .../exercises/WhenWorkingWithAPetQueue.java | 5 - .../exercises/WhenWorkingWithASetOfPets.java | 9 -- .../WhenWorkingWithAStackOfPets.java | 4 +- .../katas/WhenBookingPetsIntoAPetHotel.java | 133 ------------------ 17 files changed, 15 insertions(+), 371 deletions(-) delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java delete mode 100644 src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java index a37af38b..ca7dc591 100644 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java @@ -23,13 +23,14 @@ public PetAdder(int petCount) { this.petCount = petCount; } - public PetHotel petsCheckedIn() { - PetHotel hotel = new PetHotel(); - for(int count = 0; count < petCount; count++) { - hotel.checkIn(somePet(count)); - } - return hotel; - } +// TODO: Refact this ancient cradt +// public PetHotel petsCheckedIn() { +// PetHotel hotel = new PetHotel(); +// for(int count = 0; count < petCount; count++) { +// hotel.checkIn(somePet(count)); +// } +// return hotel; +// } private Pet somePet(int petCount) { return new Pet(someName(petCount), someBreed()); diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java deleted file mode 100644 index 89fbcf62..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingAcknowledgement.java +++ /dev/null @@ -1,7 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -public interface BookingAcknowledgement { - boolean isConfirmed(); - - boolean isOnWaitingList(); -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java deleted file mode 100644 index 054a17a3..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingConfirmation.java +++ /dev/null @@ -1,19 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -public class BookingConfirmation extends BookingResponse { - public BookingConfirmation(int number, Pet pet) { - super(number, pet); - } - - @Override - public boolean isConfirmed() { - return true; - } - - @Override - public boolean isOnWaitingList() { - return false; - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java deleted file mode 100644 index 4226fe34..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/BookingResponse.java +++ /dev/null @@ -1,32 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.concurrent.atomic.AtomicInteger; - -public abstract class BookingResponse implements BookingAcknowledgement { - private static AtomicInteger bookingNumberCounter = new AtomicInteger(); - private final int number; - private final Pet pet; - - public BookingResponse(int number, Pet pet) { - this.number = number; - this.pet = pet; - } - - public static BookingResponse confirmedFor(Pet pet) { - return new BookingConfirmation(bookingNumberCounter.incrementAndGet(), pet); - } - - public static BookingResponse waitingListFor(Pet pet) { - return new PlacedOnWaitingList(bookingNumberCounter.incrementAndGet(), pet); - } - - public Pet getPet() { - return pet; - } - - public int getNumber() { - return number; - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java deleted file mode 100644 index 7a56cf53..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/Calculator.java +++ /dev/null @@ -1,9 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -public class Calculator { - protected int field; - - public Integer calculate(String expression) { - return 0; - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java deleted file mode 100644 index b82412ed..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/CheckInStrategy.java +++ /dev/null @@ -1,7 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -public interface CheckInStrategy { - BookingResponse attemptToCheckIn(Pet pet); -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java deleted file mode 100644 index 04675e07..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/ConfirmBookingStrategy.java +++ /dev/null @@ -1,19 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.Collection; - -public class ConfirmBookingStrategy implements CheckInStrategy { - private final Collection pets; - - public ConfirmBookingStrategy(Collection pets) { - this.pets = pets; - } - - @Override - public BookingResponse attemptToCheckIn(Pet pet) { - pets.add(pet); - return BookingResponse.confirmedFor(pet); - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java deleted file mode 100644 index 5f2ab8f6..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PetHotel.java +++ /dev/null @@ -1,48 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.*; - -import static java.util.Comparator.comparing; - -public class PetHotel { - - public static final int MAXIMUM_PETS = 20; - - private Collection pets = new TreeSet<>(comparing(Pet::getName)); - private Queue waitingList = new LinkedList<>(); - - public List getPets() { - return new ArrayList<>(pets); - } - - private enum HotelAvailability { Available, Full} - - private static final Map CHECK_IN_STRATEGY = new HashMap<>(); - { - CHECK_IN_STRATEGY.put(HotelAvailability.Available, new ConfirmBookingStrategy(pets)); - CHECK_IN_STRATEGY.put(HotelAvailability.Full, new WaitingListStrategy(waitingList)); - } - - private HotelAvailability currentAvailability() { - return (pets.size() >= MAXIMUM_PETS) ? HotelAvailability.Full : HotelAvailability.Available; - } - - public BookingResponse checkIn(Pet pet) { - CheckInStrategy checkInStrategy = CHECK_IN_STRATEGY.get(currentAvailability()); - return checkInStrategy.attemptToCheckIn(pet); - } - - public Collection getWaitingList() { - return new ArrayList<>(waitingList); - } - - public void checkOut(Pet pet) { - pets.remove(pet); - - if (!waitingList.isEmpty()) { - checkIn(waitingList.poll()); - } - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java deleted file mode 100644 index 26007683..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/PlacedOnWaitingList.java +++ /dev/null @@ -1,19 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -public class PlacedOnWaitingList extends BookingResponse { - public PlacedOnWaitingList(int number, Pet pet) { - super(number, pet); - } - - @Override - public boolean isConfirmed() { - return false; - } - - @Override - public boolean isOnWaitingList() { - return true; - } -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java deleted file mode 100644 index ea9d08a1..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/SpecialisedPetHotel.java +++ /dev/null @@ -1,19 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import java.util.ArrayList; -import java.util.List; - -public class SpecialisedPetHotel { - - List pets = new ArrayList<>(); - - public void checkIn(T pet) { - pets.add(pet); - } - - public List getPets() { - return new ArrayList<>(pets); - } - - -} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java deleted file mode 100644 index 0ea45147..00000000 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/WaitingListStrategy.java +++ /dev/null @@ -1,20 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.katas; - -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.Collection; - -public class WaitingListStrategy implements CheckInStrategy { - private final Collection relevantPets; - - public WaitingListStrategy(Collection pets) { - this.relevantPets = pets; - } - - @Override - public BookingResponse attemptToCheckIn(Pet pet) { - relevantPets.add(pet); - return BookingResponse.waitingListFor(pet); - } - -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java index 80f0b910..6251b5e3 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java @@ -3,7 +3,6 @@ import com.google.common.collect.Lists; import org.junit.Test; -import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -17,7 +16,6 @@ public void should_add_Fido_to_the_list_of_pets() { List names = Lists.newArrayList(); // TODO - names.add("Fido"); assertThat(names, hasItems("Fido")); } @@ -26,7 +24,6 @@ public void should_add_Fido_to_the_list_of_pets() { public void should_remove_Fido_from_the_list_of_pets() { List names = Lists.newArrayList("Felix","Fido","Spot"); // TODO - names.remove("Fido"); assertThat(names, hasItems("Felix","Spot")); } @@ -36,7 +33,6 @@ public void should_remove_the_first_pet_from_the_list_of_pets() { List names = Lists.newArrayList("Felix","Fido","Spot"); // TODO - names.remove(0); assertThat(names, hasItems("Fido","Spot")); } @@ -47,8 +43,7 @@ public void should_make_a_list_of_cats_and_dogs() { List dogs = Lists.newArrayList("Fido","Rover"); // TODO - List catsAndDogs = new ArrayList(cats); - catsAndDogs.addAll(dogs); + List catsAndDogs = null; assertThat(catsAndDogs, hasItems("Felix","Spot","Fido","Rover")); } @@ -59,8 +54,7 @@ public void should_put_the_dogs_among_the_cats() { List dogs = Lists.newArrayList("Fido","Rover"); // TODO - List catsAndDogs = new ArrayList(cats); - catsAndDogs.addAll(1,dogs); + List catsAndDogs = null; assertThat(catsAndDogs, hasItems("Felix","Fido","Rover","Spot")); } @@ -70,7 +64,6 @@ public void should_organise_pets_in_alphabetical_order() { List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); // TODO - pets.sort(Comparator.naturalOrder()); assertThat(pets, hasItems("Felix","Fido","Rover","Spot")); } @@ -80,7 +73,6 @@ public void should_organise_pets_in_reverse_alphabetical_order() { List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); // TODO - pets.sort(Comparator.reverseOrder()); assertThat(pets, hasItems("Spot","Rover","Fido","Felix")); } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java index 3bc14d3a..6d767717 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java @@ -20,7 +20,6 @@ public void pets_can_be_found_by_their_name() { pets.put("Fido", fido); // TODO - assertThat(pets.get("Fido"), equalTo(fido)); } @Test @@ -36,7 +35,6 @@ public void should_be_able_to_get_a_default_value_if_no_matching_key_is_present( Pet retrievedPet = pets.getOrDefault("Rover", stray); // TODO - assertThat(retrievedPet, equalTo(stray)); } @Test @@ -50,13 +48,12 @@ public void the_map_keys_should_be_the_pet_names() { pets.put("Felix", felix); // TODO - assertThat(pets.keySet(), containsInAnyOrder("Fido","Felix")); } @Test public void the_map_should_store_pets_in_alphabetical_order() { // TODO: Instantiate the correct type of Map - NavigableMap pets = new TreeMap<>(); + NavigableMap pets = null; pets.put("Rover", Pet.dog().named("Rover")); pets.put("Felix", Pet.cat().named("Felix")); @@ -68,7 +65,7 @@ public void the_map_should_store_pets_in_alphabetical_order() { @Test public void the_map_should_store_pets_in_the_order_they_where_added() { // TODO: Instantiate the correct type of Map - Map pets = new LinkedHashMap<>(); + Map pets = null; pets.put("Spot", Pet.cat().named("Spot")); pets.put("Rover", Pet.dog().named("Rover")); @@ -81,7 +78,7 @@ public void the_map_should_store_pets_in_the_order_they_where_added() { @Test public void the_map_should_store_pet_leaders_by_breed() { // TODO: Create an EnumMap to define a pet leader for each breed - EnumMap petLeaders = new EnumMap<>(Breed.class); + EnumMap petLeaders = null; petLeaders.put(Breed.Cat, Pet.cat().named("Felix")); petLeaders.put(Breed.Dog, Pet.dog().named("Lassie")); diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java index c4007529..9f054388 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java @@ -6,9 +6,6 @@ import java.util.LinkedList; import java.util.Queue; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - public class WhenWorkingWithAPetQueue { @Test @@ -21,7 +18,6 @@ public void should_add_Fido_to_the_end_of_the_queue() { Pet nextInLine = waitingList.poll(); // TODO - assertThat(nextInLine.getName(), equalTo("Felix")); } @Test @@ -34,7 +30,6 @@ public void should_see_who_is_at_the_top_of_the_queue_without_removing_it() { Pet nextInLine = waitingList.peek(); // TODO - assertThat(nextInLine.getName(), equalTo("Felix")); } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java index b13215b4..24037f48 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java @@ -5,10 +5,6 @@ import java.util.Set; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertThat; - public class WhenWorkingWithASetOfPets { @Test @@ -16,9 +12,6 @@ public void should_add_Fido_to_the_set_of_pets() { Set names = Sets.newHashSet(); // TODO - names.add("Fido"); - - assertThat(names, contains("Fido")); } @Test @@ -30,7 +23,6 @@ public void a_set_of_pets_should_not_contain_duplicates() { names.add("Fido"); // TODO - assertThat(names, containsInAnyOrder("Fido","Felix")); } @Test @@ -40,7 +32,6 @@ public void adding_several_pets() { names.addAll(Sets.newHashSet("Felix","Spot")); // TODO - assertThat(names, containsInAnyOrder("Fido","Felix","Spot")); } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java index 9cad2703..bf69c4c5 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java @@ -20,7 +20,7 @@ public void should_store_pets_in_a_stack() { pets.push(Pet.dog().named("Fido")); // TODO: Retrieve the last pet put on the list - Pet lastPet = pets.pop(); + Pet lastPet = null; assertThat(lastPet.getName(),equalTo("Fido")); assertThat(pets.size(), equalTo(1)); @@ -35,7 +35,7 @@ public void should_see_the_next_item_in_a_stack() { pets.push(Pet.dog().named("Fido")); // TODO: Retrieve the last pet put on the list - Pet lastPet = pets.peek(); + Pet lastPet = null; assertThat(lastPet.getName(),equalTo("Fido")); assertThat(pets.size(), equalTo(2)); diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java index db45270c..5486b552 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java @@ -1,187 +1,54 @@ package serenitylabs.tutorials.vetclinic.collections.katas; import org.junit.Test; -import serenitylabs.tutorials.vetclinic.Pet; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; public class WhenBookingPetsIntoAPetHotel { @Test public void the_hotel_should_initially_have_no_pets_booked() { - // GIVEN - PetHotel hotel = new PetHotel(); - - // THEN - assertThat(hotel.getPets(), hasSize(0)); } @Test public void should_be_able_to_check_a_pet_into_the_hotel() throws Exception { - // GIVEN - PetHotel hotel = new PetHotel(); - Pet fido = Pet.dog().named("Fido"); - - // WHEN - hotel.checkIn(fido); - - // THEN - assertThat(hotel.getPets(), hasItem(fido)); } @Test public void should_be_able_to_check_in_several_pets() throws Exception { - // GIVEN - PetHotel hotel = new PetHotel(); - Pet fido = Pet.dog().named("Fido"); - Pet felix = Pet.cat().named("Felix"); - - // WHEN - hotel.checkIn(fido); - hotel.checkIn(felix); - - // THEN - assertThat(hotel.getPets(), hasItems(fido,felix)); } @Test public void should_not_be_able_to_check_in_the_same_pet_twice() throws Exception { - // GIVEN - PetHotel hotel = new PetHotel(); - Pet fido = Pet.dog().named("Fido"); - Pet felix = Pet.cat().named("Felix"); - - // AND - hotel.checkIn(fido); - hotel.checkIn(felix); - - // WHEN - hotel.checkIn(fido); - - // THEN - assertThat(hotel.getPets(), containsInAnyOrder(fido, felix)); } @Test public void should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order() throws Exception { - // GIVEN - PetHotel hotel = new PetHotel(); - Pet hazel = Pet.rabbit().named("Hazel"); - Pet rover = Pet.dog().named("Rover"); - Pet felix = Pet.cat().named("Felix"); - - // WHEN - hotel.checkIn(hazel); - hotel.checkIn(rover); - hotel.checkIn(felix); - - // THEN - assertThat(hotel.getPets(), contains(felix, hazel, rover)); } @Test public void should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet() throws Exception { - // GIVEN - PetHotel hotel = new PetHotel(); - Pet fido = Pet.dog().named("Fido"); - - // WHEN - BookingResponse confirmation = hotel.checkIn(fido); - - // THEN - assertThat(confirmation.getNumber(), greaterThan(0)); - assertThat(confirmation.getPet(), equalTo(fido)); - assertThat(confirmation.isConfirmed(), equalTo(true)); } @Test public void should_not_be_able_to_check_in_pets_beyond_hotel_capacity() throws Exception { - // GIVEN - PetHotel hotel = APetHotel.with(PetHotel.MAXIMUM_PETS).petsCheckedIn(); - - // WHEN - hotel.checkIn(Pet.dog().named("Lassie")); - - assertThat(hotel.getPets(), hasSize(20)); } - /** - * - * Refactor checkIn method to return a BookingAcknowledgement interface, which has two methods: isConfirmed() - * and isOnWaitingList(). - * You will need to complete the APetHotel helper class used in the Given. - */ @Test public void should_notify_owner_that_the_hotel_is_full() throws Exception { - // GIVEN - PetHotel hotel = APetHotel.with(20).petsCheckedIn(); - - // WHEN - BookingResponse response = hotel.checkIn(Pet.dog().named("Lassie")); - - // THEN - assertThat(response.isConfirmed(), is(false)); - assertThat(response.isOnWaitingList(), is(true)); - } @Test public void should_place_pets_on_a_waiting_list_when_the_hotel_is_full() throws Exception { - // GIVEN - PetHotel hotel = APetHotel.with(20).petsCheckedIn(); - Pet lassie = Pet.dog().named("Lassie"); - - // WHEN - hotel.checkIn(lassie); - - // THEN - assertThat(hotel.getWaitingList(), hasItem(lassie)); } - @Test public void pets_on_the_waiting_list_should_be_added_to_the_hotel_when_a_place_is_freed() throws Exception { - // GIVEN - PetHotel hotel = APetHotel.with(19).petsCheckedIn(); - Pet fido = Pet.dog().named("Fido"); - Pet lassie = Pet.dog().named("Lassie"); - - hotel.checkIn(fido); - - // WHEN - hotel.checkIn(lassie); - // AND - hotel.checkOut(fido); - - // THEN - assertThat(hotel.getPets(), hasItem(lassie)); } @Test public void pets_on_the_waiting_list_should_be_admitted_on_a_first_come_first_served_basis() throws Exception { - // GIVEN - PetHotel hotel = APetHotel.with(19).petsCheckedIn(); - Pet felix = Pet.cat().named("Felix"); - - Pet fido = Pet.dog().named("Fido"); - Pet lassie = Pet.dog().named("Lassie"); - - - hotel.checkIn(felix); - - // WHEN - hotel.checkIn(fido); - hotel.checkIn(lassie); - // AND - hotel.checkOut(felix); - - // THEN - assertThat(hotel.getPets(), hasItem(fido)); - assertThat(hotel.getPets(), not(hasItem(lassie))); } } From 577ccbe71d8d0a497f326e8d7760185dbdbaae5a Mon Sep 17 00:00:00 2001 From: John Smart Date: Thu, 18 Aug 2016 12:18:16 +0100 Subject: [PATCH 03/13] Test refactoring --- .../collections/exercises/WhenWorkingWithAListOfPetNames.java | 2 -- .../collections/exercises/WhenWorkingWithAPetMap.java | 2 -- .../collections/exercises/WhenWorkingWithAPetQueue.java | 4 ---- 3 files changed, 8 deletions(-) diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java index 6251b5e3..d0a9ca90 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java @@ -3,7 +3,6 @@ import com.google.common.collect.Lists; import org.junit.Test; -import java.util.Comparator; import java.util.List; import static org.hamcrest.CoreMatchers.hasItems; @@ -82,7 +81,6 @@ public void should_organise_pets_by_name_length() { List pets = Lists.newArrayList("Felix","Alfred","Spot"); // TODO - pets.sort(Comparator.comparing(String::length)); assertThat(pets, hasItems("Spot","Felix","Alfred")); } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java index 6d767717..b12fc88f 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java @@ -32,8 +32,6 @@ public void should_be_able_to_get_a_default_value_if_no_matching_key_is_present( pets.put("Fido", fido); pets.put("Stray", stray); - Pet retrievedPet = pets.getOrDefault("Rover", stray); - // TODO } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java index 9f054388..e9be919f 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java @@ -15,8 +15,6 @@ public void should_add_Fido_to_the_end_of_the_queue() { waitingList.add(Pet.cat().named("Felix")); waitingList.add(Pet.dog().named("Fido")); - Pet nextInLine = waitingList.poll(); - // TODO } @@ -27,8 +25,6 @@ public void should_see_who_is_at_the_top_of_the_queue_without_removing_it() { waitingList.add(Pet.cat().named("Felix")); waitingList.add(Pet.dog().named("Fido")); - Pet nextInLine = waitingList.peek(); - // TODO } From 9fb60cecd26a39ec840d061461932b1c5eb955b5 Mon Sep 17 00:00:00 2001 From: John Smart Date: Thu, 18 Aug 2016 12:21:59 +0100 Subject: [PATCH 04/13] Test refactoring --- .../tutorials/vetclinic/collections/katas/APetHotel.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java index ca7dc591..6a5c242b 100644 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java @@ -23,15 +23,6 @@ public PetAdder(int petCount) { this.petCount = petCount; } -// TODO: Refact this ancient cradt -// public PetHotel petsCheckedIn() { -// PetHotel hotel = new PetHotel(); -// for(int count = 0; count < petCount; count++) { -// hotel.checkIn(somePet(count)); -// } -// return hotel; -// } - private Pet somePet(int petCount) { return new Pet(someName(petCount), someBreed()); } From b6adf5b6741b6cf0f65ab7e32f648f9ba05b41e6 Mon Sep 17 00:00:00 2001 From: John Smart Date: Sun, 21 Aug 2016 11:31:49 +0100 Subject: [PATCH 05/13] Improved hamcrest matchers --- .../WhenWorkingWithAListOfPetNames.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java index d0a9ca90..710a5e0a 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java @@ -5,7 +5,7 @@ import java.util.List; -import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertThat; public class WhenWorkingWithAListOfPetNames { @@ -16,7 +16,7 @@ public void should_add_Fido_to_the_list_of_pets() { // TODO - assertThat(names, hasItems("Fido")); + assertThat(names, contains("Fido")); } @Test @@ -24,7 +24,7 @@ public void should_remove_Fido_from_the_list_of_pets() { List names = Lists.newArrayList("Felix","Fido","Spot"); // TODO - assertThat(names, hasItems("Felix","Spot")); + assertThat(names, contains("Felix","Spot")); } @Test @@ -33,7 +33,7 @@ public void should_remove_the_first_pet_from_the_list_of_pets() { // TODO - assertThat(names, hasItems("Fido","Spot")); + assertThat(names, contains("Fido","Spot")); } @Test @@ -44,7 +44,7 @@ public void should_make_a_list_of_cats_and_dogs() { // TODO List catsAndDogs = null; - assertThat(catsAndDogs, hasItems("Felix","Spot","Fido","Rover")); + assertThat(catsAndDogs, contains("Felix","Spot","Fido","Rover")); } @Test @@ -55,7 +55,7 @@ public void should_put_the_dogs_among_the_cats() { // TODO List catsAndDogs = null; - assertThat(catsAndDogs, hasItems("Felix","Fido","Rover","Spot")); + assertThat(catsAndDogs, contains("Felix","Fido","Rover","Spot")); } @Test @@ -64,7 +64,7 @@ public void should_organise_pets_in_alphabetical_order() { // TODO - assertThat(pets, hasItems("Felix","Fido","Rover","Spot")); + assertThat(pets, contains("Felix","Fido","Rover","Spot")); } @Test @@ -73,7 +73,7 @@ public void should_organise_pets_in_reverse_alphabetical_order() { // TODO - assertThat(pets, hasItems("Spot","Rover","Fido","Felix")); + assertThat(pets, contains("Spot","Rover","Fido","Felix")); } @Test @@ -82,7 +82,7 @@ public void should_organise_pets_by_name_length() { // TODO - assertThat(pets, hasItems("Spot","Felix","Alfred")); + assertThat(pets, contains("Spot","Felix","Alfred")); } } From 4ebd448d0e4be3372d8662555d3afe7f3009ad6f Mon Sep 17 00:00:00 2001 From: John Smart Date: Tue, 23 Aug 2016 11:14:50 +0100 Subject: [PATCH 06/13] Clearer instructions --- README.md | 6 +++--- .../tutorials/vetclinic/collections/katas/README.md | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e296357..89b3aaf6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This project is used as the basis of a number of tutorials and exercises, as part of the *Professional Java Development and Test Automation Skills* program (see http://johnfergusonsmart.com/products). Each tutorial explores a different technique or practice essential to modern Java developers or Engineers in Test. -These exercises are designed to help you become familiar with using collections in Java. The first ones are designed to help you learn the Java Collections APIs, whereas the second +These exercises are designed to help you become familiar with using collections in Java. ## Working with collections @@ -18,9 +18,9 @@ These exercises are designed to help you become familiar with using collections ### Step 6 - Implement all the tests in the `WhenWorkingWithAStackOfPets` class. -## Applying what you have learned +## Kata -### Kata 1 - Calculating sums +See the detailed instructions in the test/java/serenitylabs/tutorials/vetclinic/collections/katas package. diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md index ca7b0781..1eea8a54 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md @@ -2,6 +2,8 @@ ## Booking pets into a pet hotel +In this kata, we are helping a vet clinic open a hotel for pets on the premises. Pet owners can bring their pets to the hotel and check them in if there is an available room. If no room is available, the pet will be placed on a waiting list. Whenever a pet checks out, a room is freed to the first animal on the waiting list is automatically checked in. + The aim of this kata is to implement a Pet hotel with the following requirements: - Pet owners should be able to check their pet into the hotel From 7cec6d97715a0c645da74d55d6ff4f6c625d637b Mon Sep 17 00:00:00 2001 From: pravyada Date: Tue, 23 Aug 2016 18:10:09 +0530 Subject: [PATCH 07/13] Tutorial 1 impelemented as per the steps of Builder Pattern. --- src/main/java/domain/Dog.java | 70 +++++++++++++++++++++ src/test/java/domain/WhenCreateANewDog.java | 20 ++++++ 2 files changed, 90 insertions(+) create mode 100644 src/main/java/domain/Dog.java create mode 100644 src/test/java/domain/WhenCreateANewDog.java diff --git a/src/main/java/domain/Dog.java b/src/main/java/domain/Dog.java new file mode 100644 index 00000000..ee555f0e --- /dev/null +++ b/src/main/java/domain/Dog.java @@ -0,0 +1,70 @@ +package domain; + +// Immutable java class without setter methods +// Builder pattern used +/** + * @author pravyada + * + */ +public class Dog { + + private final String name; + private final String breed; + private final String color; + + + /** + * @param name + * @param breed + * @param color + */ + public Dog(String name, String breed, String color) { + this.name = name; + this.breed = breed; + this.color = color; + } + + /** + * @return String + */ + public String getName() { + return name; + } + + /** + * @return String + */ + public String getBreed() { + return breed; + } + + /** + * @return the color + */ + public String getColor() { + return color; + } + + public static DogBuilder called(String name) { + return new DogBuilder(name); + } + + public static class DogBuilder { + private final String name; + private String breed; + + public DogBuilder(String name) { + this.name = name; + } + + public DogBuilder ofBreed(String breed) { + this.breed = breed; + return this; + } + + public Dog ofColor(String color) { + return new Dog(name, breed, color); + } + + } +} diff --git a/src/test/java/domain/WhenCreateANewDog.java b/src/test/java/domain/WhenCreateANewDog.java new file mode 100644 index 00000000..7c3c2471 --- /dev/null +++ b/src/test/java/domain/WhenCreateANewDog.java @@ -0,0 +1,20 @@ +package domain; + +import org.junit.Test; + +import junit.framework.Assert; + +@SuppressWarnings("deprecation") +public class WhenCreateANewDog { + @Test + public void a_new_dog_should_have_a_name() { + // Note.... constructor with too many parameters is hard to read + //Dog fido = new Dog("Fido", "LabroDog", LocalDate.now()); + + // Using Builder pattern + Dog fido = Dog.called("Fido").ofBreed("LabroDog").ofColor("black"); + Assert.assertEquals("Fido", fido.getName()); + Assert.assertEquals("LabroDog", fido.getBreed()); + Assert.assertEquals("black", fido.getColor()); + } +} From 17f20c2a11f0d52e2f42b14bad538fbb1ace6646 Mon Sep 17 00:00:00 2001 From: John Ferguson Smart Date: Tue, 13 Sep 2016 18:54:49 +0100 Subject: [PATCH 08/13] Create circle.yml --- circle.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000..cdee9fa7 --- /dev/null +++ b/circle.yml @@ -0,0 +1,9 @@ +machine: + java: + version: oraclejdk8 + +test: + post: + - mkdir -p $CIRCLE_TEST_REPORTS/junit/ + - find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; + - find . -type f -regex ".*/target/site/serenity/SERENITY-JUNIT-*.xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \; From bd86a8ebf81e1a9b8c0fbdfe19507e54c9ad8f4a Mon Sep 17 00:00:00 2001 From: John Ferguson Smart Date: Tue, 20 Sep 2016 10:26:08 +0100 Subject: [PATCH 09/13] Update README.md --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 89b3aaf6..1eea8a54 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,81 @@ -# Vet Clinic Tutorial Project +# Collections Katas + +## Booking pets into a pet hotel + +In this kata, we are helping a vet clinic open a hotel for pets on the premises. Pet owners can bring their pets to the hotel and check them in if there is an available room. If no room is available, the pet will be placed on a waiting list. Whenever a pet checks out, a room is freed to the first animal on the waiting list is automatically checked in. -This project is used as the basis of a number of tutorials and exercises, as part of the *Professional Java Development and Test Automation Skills* program (see http://johnfergusonsmart.com/products). Each tutorial explores a different technique or practice essential to modern Java developers or Engineers in Test. +The aim of this kata is to implement a Pet hotel with the following requirements: -These exercises are designed to help you become familiar with using collections in Java. + - Pet owners should be able to check their pet into the hotel + - Pet owners should receive a confirmation that their pet has been successfully checked in + - The hotel owner should be able to list all of the pets in the hotel in alphabetical order + - The hotel should have a maximum capacity of 20 animals. + - When a pet owner checks in their pet and the hotel is full, they should receive a confirmation that their pet has been placed on a waiting list. + - When a pet checks out of the hotel, the first animal on the waiting list should be automatically checked in. + +When you first do the exercise, implement the features by progressively making all of the acceptance tests in the pass, one after the other. The `WhenBookingPetsIntoAPetHotel` test class contains a sequence of unit tests for each feature to be implemented. The last line in each test is a Hamcrest assertion that is commented out. Uncomment the assertion, then follow the steps below to implement each feature and make the tests pass. -## Working with collections +Once you have finished, repeat the exercise, but first deleting all of the tests and then rewriting them using a TDD approach (i.e. Write a failing test for a feature, make it pass, refactor the code, move to the next feature). -### Step 1 - Implement the tests in the `WhenWorkingWithAListOfPetNames` class. +## The Steps -### Step 2 - Implement the tests in the `WhenWorkingWithAListOfPets` class. +# Step 1 - Check a pet into the hotel (part 1) +_Test case:_ `the_hotel_should_initially_have_no_pets_booked()` -### Step 3 - Implement all the tests in the `WhenWorkingWithASetOfPets` class. +Create a new class `PetHotel` and give it a method `getPets()` that returns null. Make sure the test fails, then get the `getPets()` method to return an empty collection of `Pet` instances. -### Step 4 - Implement all the tests in the `WhenWorkingWithAPetMap` class. +# Step 2 - Check a pet into the hotel (part 2) -### Step 5 - Implement all the tests in the `WhenWorkingWithAPetQueue` class. +_Test case:_ `should_be_able_to_check_a_pet_into_the_hotel()` -### Step 6 - Implement all the tests in the `WhenWorkingWithAStackOfPets` class. +Add a method `checkIn()` to the `PetHotel` class, that takes a `Pet` as a parameter, and demonstrate that when you check a pet into the hotel, it can be retrieved via the `getPets()` method. Implement the list of pets in the `PetHotel` class as an `ArrayList`. -## Kata +# Step 3 - Check a pet into the hotel (part 3) -See the detailed instructions in the test/java/serenitylabs/tutorials/vetclinic/collections/katas package. +_Test case:_ `should_be_able_to_check_in_several_pets()` +Demonstrate that you can check several pets into the hotel, and that they all can be retrieved via the `getPets()` method. +# Step 4 - Check a pet into the hotel (part 4) +_Test case:_ `should_not_be_able_to_check_in_the_same_pet_twice()` + +Demonstrate that if you check in the same pet twice, it should have no effect on the current pet list. Refactor the pet list field to use a `TreeMap` instead of an `ArrayList`. + +# Step 5 - Pet owners should receive a confirmation that their pet has been successfully checked in + +_Test case:_ `should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet()` + +Demonstrate that when an owner checks in a pet, they receive a `BookingResponse` object which contains a reference to the pet, a booking number, and a method `isConfirmed()` that returns `true`. + + +# Step 6 - The hotel owner should be able to list all of the pets in the hotel in alphabetical order + +_Test case:_ `should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order()` + +Make this work by refactoring the pet list field to use a `TreeMap` with a Java 8 comparator. + +# Step 7 - The hotel should have a maximum capacity of 20 animals. + +_Test case:_ `should_not_be_able_to_check_in_pets_beyond_hotel_capacity()` + +This test should check that when an owner checks in a pet when the hotel is full, the pet is not added to the pet list. + +# Step 8 + +_Test case:_ `should_notify_owner_that_the_hotel_is_full()` + +Ensure that when an owner checks in a pet to a full hotel, the hotel returns a `Response` that indicates that the booking is not confirmed (`isConfirmed()` returns false), and that the pet has been placed on a waiting list (via a new method, 'isOnWaitingList()` is true). + +# Step 9 + +_Test case:_ `pets_on_the_waiting_list_should_be_added_to_the_hotel_when_a_place_is_freed()` + +Ensure that when a pet checks out of the hotel, the first pet on the waiting list is automatically checked in. + +# Step 10 + +_Test case:_ `pets_on_the_waiting_list_should_be_admitted_on_a_first_come_first_served_basis()` + +Ensure that pets on the waiting list are checked in on a first-come-first-served basis. From a4827a6505d5e64df9309282450b6efe8e740248 Mon Sep 17 00:00:00 2001 From: John Smart Date: Tue, 20 Sep 2016 10:48:03 +0100 Subject: [PATCH 10/13] Removed irrelevant tests for this exercise --- .../WhenWorkingWithAListOfPetNames.java | 88 ------------------- .../exercises/WhenWorkingWithAListOfPets.java | 25 ------ .../exercises/WhenWorkingWithAPetMap.java | 88 ------------------- .../exercises/WhenWorkingWithAPetQueue.java | 32 ------- .../exercises/WhenWorkingWithASetOfPets.java | 38 -------- .../WhenWorkingWithAStackOfPets.java | 43 --------- .../vetclinic/collections/katas/README.md | 81 ----------------- 7 files changed, 395 deletions(-) delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java delete mode 100644 src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java deleted file mode 100644 index 710a5e0a..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPetNames.java +++ /dev/null @@ -1,88 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import com.google.common.collect.Lists; -import org.junit.Test; - -import java.util.List; - -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertThat; - -public class WhenWorkingWithAListOfPetNames { - - @Test - public void should_add_Fido_to_the_list_of_pets() { - List names = Lists.newArrayList(); - - // TODO - - assertThat(names, contains("Fido")); - } - - @Test - public void should_remove_Fido_from_the_list_of_pets() { - List names = Lists.newArrayList("Felix","Fido","Spot"); - // TODO - - assertThat(names, contains("Felix","Spot")); - } - - @Test - public void should_remove_the_first_pet_from_the_list_of_pets() { - List names = Lists.newArrayList("Felix","Fido","Spot"); - - // TODO - - assertThat(names, contains("Fido","Spot")); - } - - @Test - public void should_make_a_list_of_cats_and_dogs() { - List cats = Lists.newArrayList("Felix","Spot"); - List dogs = Lists.newArrayList("Fido","Rover"); - - // TODO - List catsAndDogs = null; - - assertThat(catsAndDogs, contains("Felix","Spot","Fido","Rover")); - } - - @Test - public void should_put_the_dogs_among_the_cats() { - List cats = Lists.newArrayList("Felix","Spot"); - List dogs = Lists.newArrayList("Fido","Rover"); - - // TODO - List catsAndDogs = null; - - assertThat(catsAndDogs, contains("Felix","Fido","Rover","Spot")); - } - - @Test - public void should_organise_pets_in_alphabetical_order() { - List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); - - // TODO - - assertThat(pets, contains("Felix","Fido","Rover","Spot")); - } - - @Test - public void should_organise_pets_in_reverse_alphabetical_order() { - List pets = Lists.newArrayList("Felix","Spot","Fido","Rover"); - - // TODO - - assertThat(pets, contains("Spot","Rover","Fido","Felix")); - } - - @Test - public void should_organise_pets_by_name_length() { - List pets = Lists.newArrayList("Felix","Alfred","Spot"); - - // TODO - - assertThat(pets, contains("Spot","Felix","Alfred")); - } - -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java deleted file mode 100644 index 14d0090a..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAListOfPets.java +++ /dev/null @@ -1,25 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import org.junit.Test; -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; - -public class WhenWorkingWithAListOfPets { - - @Test - public void should_store_a_list_of_pets() { - - List pets = new ArrayList<>(); - - pets.add(Pet.cat().named("Felix")); - pets.add(Pet.dog().named("Fido")); - - // TODO: Implement the equals and hashcode methods in the Pet class to make this work - assertThat(pets, hasItem(Pet.dog().named("Fido"))); - } -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java deleted file mode 100644 index b12fc88f..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetMap.java +++ /dev/null @@ -1,88 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import org.junit.Test; -import serenitylabs.tutorials.vetclinic.Breed; -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.*; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; - -public class WhenWorkingWithAPetMap { - - @Test - public void pets_can_be_found_by_their_name() { - Map pets = new HashMap<>(); - - Pet fido = Pet.dog().named("Fido"); - - pets.put("Fido", fido); - - // TODO - } - - @Test - public void should_be_able_to_get_a_default_value_if_no_matching_key_is_present() { - Map pets = new HashMap<>(); - - Pet fido = Pet.dog().named("Fido"); - Pet stray = Pet.dog().named("Stray"); - - pets.put("Fido", fido); - pets.put("Stray", stray); - - // TODO - } - - @Test - public void the_map_keys_should_be_the_pet_names() { - Map pets = new HashMap<>(); - - Pet fido = Pet.dog().named("Fido"); - Pet felix = Pet.cat().named("Felix"); - - pets.put("Fido", fido); - pets.put("Felix", felix); - - // TODO - } - - @Test - public void the_map_should_store_pets_in_alphabetical_order() { - // TODO: Instantiate the correct type of Map - NavigableMap pets = null; - - pets.put("Rover", Pet.dog().named("Rover")); - pets.put("Felix", Pet.cat().named("Felix")); - pets.put("Spot", Pet.cat().named("Spot")); - - assertThat(pets.keySet(), contains("Felix","Rover","Spot")); - } - - @Test - public void the_map_should_store_pets_in_the_order_they_where_added() { - // TODO: Instantiate the correct type of Map - Map pets = null; - - pets.put("Spot", Pet.cat().named("Spot")); - pets.put("Rover", Pet.dog().named("Rover")); - pets.put("Felix", Pet.cat().named("Felix")); - pets.put("Fido", Pet.cat().named("Fido")); - - assertThat(pets.keySet(), contains("Spot", "Rover","Felix", "Fido")); - } - - @Test - public void the_map_should_store_pet_leaders_by_breed() { - // TODO: Create an EnumMap to define a pet leader for each breed - EnumMap petLeaders = null; - - petLeaders.put(Breed.Cat, Pet.cat().named("Felix")); - petLeaders.put(Breed.Dog, Pet.dog().named("Lassie")); - petLeaders.put(Breed.Rabbit, Pet.cat().named("Hazel")); - - assertThat(petLeaders.get(Breed.Dog).getName(), equalTo("Lassie")); - } - -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java deleted file mode 100644 index e9be919f..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAPetQueue.java +++ /dev/null @@ -1,32 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import org.junit.Test; -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.LinkedList; -import java.util.Queue; - -public class WhenWorkingWithAPetQueue { - - @Test - public void should_add_Fido_to_the_end_of_the_queue() { - Queue waitingList = new LinkedList<>(); - - waitingList.add(Pet.cat().named("Felix")); - waitingList.add(Pet.dog().named("Fido")); - - // TODO - } - - @Test - public void should_see_who_is_at_the_top_of_the_queue_without_removing_it() { - Queue waitingList = new LinkedList<>(); - - waitingList.add(Pet.cat().named("Felix")); - waitingList.add(Pet.dog().named("Fido")); - - // TODO - } - - -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java deleted file mode 100644 index 24037f48..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithASetOfPets.java +++ /dev/null @@ -1,38 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import com.google.common.collect.Sets; -import org.junit.Test; - -import java.util.Set; - -public class WhenWorkingWithASetOfPets { - - @Test - public void should_add_Fido_to_the_set_of_pets() { - Set names = Sets.newHashSet(); - - // TODO - } - - @Test - public void a_set_of_pets_should_not_contain_duplicates() { - Set names = Sets.newHashSet(); - - names.add("Fido"); - names.add("Felix"); - names.add("Fido"); - - // TODO - } - - @Test - public void adding_several_pets() { - Set names = Sets.newHashSet("Fido","Felix"); - - names.addAll(Sets.newHashSet("Felix","Spot")); - - // TODO - } - - -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java deleted file mode 100644 index bf69c4c5..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/exercises/WhenWorkingWithAStackOfPets.java +++ /dev/null @@ -1,43 +0,0 @@ -package serenitylabs.tutorials.vetclinic.collections.exercises; - -import org.junit.Test; -import serenitylabs.tutorials.vetclinic.Pet; - -import java.util.Deque; -import java.util.LinkedList; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - -public class WhenWorkingWithAStackOfPets { - - @Test - public void should_store_pets_in_a_stack() { - - Deque pets = new LinkedList<>(); - - pets.push(Pet.cat().named("Felix")); - pets.push(Pet.dog().named("Fido")); - - // TODO: Retrieve the last pet put on the list - Pet lastPet = null; - - assertThat(lastPet.getName(),equalTo("Fido")); - assertThat(pets.size(), equalTo(1)); - } - - @Test - public void should_see_the_next_item_in_a_stack() { - - Deque pets = new LinkedList<>(); - - pets.push(Pet.cat().named("Felix")); - pets.push(Pet.dog().named("Fido")); - - // TODO: Retrieve the last pet put on the list - Pet lastPet = null; - - assertThat(lastPet.getName(),equalTo("Fido")); - assertThat(pets.size(), equalTo(2)); - } -} diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md deleted file mode 100644 index 1eea8a54..00000000 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# Collections Katas - -## Booking pets into a pet hotel - -In this kata, we are helping a vet clinic open a hotel for pets on the premises. Pet owners can bring their pets to the hotel and check them in if there is an available room. If no room is available, the pet will be placed on a waiting list. Whenever a pet checks out, a room is freed to the first animal on the waiting list is automatically checked in. - -The aim of this kata is to implement a Pet hotel with the following requirements: - - - Pet owners should be able to check their pet into the hotel - - Pet owners should receive a confirmation that their pet has been successfully checked in - - The hotel owner should be able to list all of the pets in the hotel in alphabetical order - - The hotel should have a maximum capacity of 20 animals. - - When a pet owner checks in their pet and the hotel is full, they should receive a confirmation that their pet has been placed on a waiting list. - - When a pet checks out of the hotel, the first animal on the waiting list should be automatically checked in. - -When you first do the exercise, implement the features by progressively making all of the acceptance tests in the pass, one after the other. The `WhenBookingPetsIntoAPetHotel` test class contains a sequence of unit tests for each feature to be implemented. The last line in each test is a Hamcrest assertion that is commented out. Uncomment the assertion, then follow the steps below to implement each feature and make the tests pass. - -Once you have finished, repeat the exercise, but first deleting all of the tests and then rewriting them using a TDD approach (i.e. Write a failing test for a feature, make it pass, refactor the code, move to the next feature). - -## The Steps - -# Step 1 - Check a pet into the hotel (part 1) -_Test case:_ `the_hotel_should_initially_have_no_pets_booked()` - -Create a new class `PetHotel` and give it a method `getPets()` that returns null. Make sure the test fails, then get the `getPets()` method to return an empty collection of `Pet` instances. - -# Step 2 - Check a pet into the hotel (part 2) - -_Test case:_ `should_be_able_to_check_a_pet_into_the_hotel()` - -Add a method `checkIn()` to the `PetHotel` class, that takes a `Pet` as a parameter, and demonstrate that when you check a pet into the hotel, it can be retrieved via the `getPets()` method. Implement the list of pets in the `PetHotel` class as an `ArrayList`. - -# Step 3 - Check a pet into the hotel (part 3) - -_Test case:_ `should_be_able_to_check_in_several_pets()` - -Demonstrate that you can check several pets into the hotel, and that they all can be retrieved via the `getPets()` method. - -# Step 4 - Check a pet into the hotel (part 4) - -_Test case:_ `should_not_be_able_to_check_in_the_same_pet_twice()` - -Demonstrate that if you check in the same pet twice, it should have no effect on the current pet list. Refactor the pet list field to use a `TreeMap` instead of an `ArrayList`. - -# Step 5 - Pet owners should receive a confirmation that their pet has been successfully checked in - -_Test case:_ `should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet()` - -Demonstrate that when an owner checks in a pet, they receive a `BookingResponse` object which contains a reference to the pet, a booking number, and a method `isConfirmed()` that returns `true`. - - -# Step 6 - The hotel owner should be able to list all of the pets in the hotel in alphabetical order - -_Test case:_ `should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order()` - -Make this work by refactoring the pet list field to use a `TreeMap` with a Java 8 comparator. - -# Step 7 - The hotel should have a maximum capacity of 20 animals. - -_Test case:_ `should_not_be_able_to_check_in_pets_beyond_hotel_capacity()` - -This test should check that when an owner checks in a pet when the hotel is full, the pet is not added to the pet list. - -# Step 8 - -_Test case:_ `should_notify_owner_that_the_hotel_is_full()` - -Ensure that when an owner checks in a pet to a full hotel, the hotel returns a `Response` that indicates that the booking is not confirmed (`isConfirmed()` returns false), and that the pet has been placed on a waiting list (via a new method, 'isOnWaitingList()` is true). - -# Step 9 - -_Test case:_ `pets_on_the_waiting_list_should_be_added_to_the_hotel_when_a_place_is_freed()` - -Ensure that when a pet checks out of the hotel, the first pet on the waiting list is automatically checked in. - -# Step 10 - -_Test case:_ `pets_on_the_waiting_list_should_be_admitted_on_a_first_come_first_served_basis()` - -Ensure that pets on the waiting list are checked in on a first-come-first-served basis. - From 08847614610e206eb339b4497114fa79db2b0242 Mon Sep 17 00:00:00 2001 From: pravyada Date: Tue, 20 Sep 2016 21:35:14 +0530 Subject: [PATCH 11/13] Code for practice exercise --- .../java/domain/BookingAcknowledgement.java | 9 ++ src/main/java/domain/BookingConfirmation.java | 27 ++++++ src/main/java/domain/BookingResponse.java | 40 +++++++++ src/main/java/domain/CheckInStrategy.java | 10 +++ .../java/domain/ConfirmBookingStrategy.java | 28 ++++++ src/main/java/domain/HotelAvailability.java | 8 ++ src/main/java/domain/PetHotel.java | 43 +++++++++ src/main/java/domain/PlacedOnWaitingList.java | 22 +++++ src/main/java/domain/WaitingListStrategy.java | 23 +++++ .../serenitylabs/tutorials/vetclinic/Pet.java | 7 +- .../collections/katas/APetHotel.java | 11 ++- .../katas/WhenBookingPetsIntoAPetHotel.java | 90 +++++++++++++++++++ 12 files changed, 316 insertions(+), 2 deletions(-) create mode 100644 src/main/java/domain/BookingAcknowledgement.java create mode 100644 src/main/java/domain/BookingConfirmation.java create mode 100644 src/main/java/domain/BookingResponse.java create mode 100644 src/main/java/domain/CheckInStrategy.java create mode 100644 src/main/java/domain/ConfirmBookingStrategy.java create mode 100644 src/main/java/domain/HotelAvailability.java create mode 100644 src/main/java/domain/PetHotel.java create mode 100644 src/main/java/domain/PlacedOnWaitingList.java create mode 100644 src/main/java/domain/WaitingListStrategy.java diff --git a/src/main/java/domain/BookingAcknowledgement.java b/src/main/java/domain/BookingAcknowledgement.java new file mode 100644 index 00000000..7a5e908a --- /dev/null +++ b/src/main/java/domain/BookingAcknowledgement.java @@ -0,0 +1,9 @@ +package domain; + +/** + * Created by pravyada on 9/20/2016. + */ +public interface BookingAcknowledgement { + boolean isConfirmed(); + boolean isOnWaiting(); +} diff --git a/src/main/java/domain/BookingConfirmation.java b/src/main/java/domain/BookingConfirmation.java new file mode 100644 index 00000000..cb716488 --- /dev/null +++ b/src/main/java/domain/BookingConfirmation.java @@ -0,0 +1,27 @@ +package domain; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by pravyada on 9/20/2016. + */ +public class BookingConfirmation extends BookingResponse +{ + + public BookingConfirmation(Pet pet, int ticketNumber) { + super(pet,ticketNumber); + } + + + @Override + public boolean isConfirmed() { + return true; + } + + @Override + public boolean isOnWaiting() { + return false; + } +} diff --git a/src/main/java/domain/BookingResponse.java b/src/main/java/domain/BookingResponse.java new file mode 100644 index 00000000..501ce9c3 --- /dev/null +++ b/src/main/java/domain/BookingResponse.java @@ -0,0 +1,40 @@ +package domain; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by pravyada on 9/20/2016. + */ +public abstract class BookingResponse implements BookingAcknowledgement { + + private static AtomicInteger ticketNumber = new AtomicInteger(); + private final Pet pet; + private int ticketNum; + + + public BookingResponse(Pet pet, int ticketNumber) { + + this.pet = pet; + this.ticketNum = ticketNumber; + } + + + public static BookingResponse confirmedFor(Pet pet) { + return new BookingConfirmation(pet, ticketNumber.incrementAndGet()); + } + + public static BookingResponse waitingListFor(Pet pet){ + return new PlacedOnWaitingList(pet, ticketNumber.incrementAndGet()); + } + + + public int getTicketNum() { + return ticketNum; + } + public Pet getPet() { + return pet; + } + +} diff --git a/src/main/java/domain/CheckInStrategy.java b/src/main/java/domain/CheckInStrategy.java new file mode 100644 index 00000000..ed7af629 --- /dev/null +++ b/src/main/java/domain/CheckInStrategy.java @@ -0,0 +1,10 @@ +package domain; + +import serenitylabs.tutorials.vetclinic.Pet; + +/** + * Created by pravyada on 9/20/2016. + */ +public interface CheckInStrategy { + public BookingResponse doCheckIn(Pet pet); +} diff --git a/src/main/java/domain/ConfirmBookingStrategy.java b/src/main/java/domain/ConfirmBookingStrategy.java new file mode 100644 index 00000000..c65bfcc6 --- /dev/null +++ b/src/main/java/domain/ConfirmBookingStrategy.java @@ -0,0 +1,28 @@ +package domain; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; + +/** + * Created by pravyada on 9/20/2016. + */ +public class ConfirmBookingStrategy implements CheckInStrategy { + + private Collection petList; + + + public ConfirmBookingStrategy(Collection petList) { + this.petList = petList; + } + + + @Override + public BookingResponse doCheckIn(Pet pet) { + petList.add(pet); + return BookingResponse.confirmedFor(pet); + } +} diff --git a/src/main/java/domain/HotelAvailability.java b/src/main/java/domain/HotelAvailability.java new file mode 100644 index 00000000..5b2b28dc --- /dev/null +++ b/src/main/java/domain/HotelAvailability.java @@ -0,0 +1,8 @@ +package domain; + +/** + * Created by pravyada on 9/20/2016. + */ +public enum HotelAvailability { + Available,Full; +} diff --git a/src/main/java/domain/PetHotel.java b/src/main/java/domain/PetHotel.java new file mode 100644 index 00000000..11b46b98 --- /dev/null +++ b/src/main/java/domain/PetHotel.java @@ -0,0 +1,43 @@ +package domain; + +import serenitylabs.tutorials.vetclinic.Pet; + +import java.util.*; + +import static java.util.Comparator.comparing; + +/** + * Created by pravyada on 9/20/2016. + */ +public class PetHotel { + public static final int MAX_SIZE = 20; + private Collection petList = new TreeSet<>(comparing(Pet::getName)); + private static Queue petsInWaitingList = new LinkedList<>(); + +private static final Map CHECK_IN_STRATEGY = new HashMap(); + { + CHECK_IN_STRATEGY .put(HotelAvailability.Available,new ConfirmBookingStrategy(petList)); + CHECK_IN_STRATEGY .put(HotelAvailability.Full,new WaitingListStrategy(petsInWaitingList)); + } + + public List getPets(){ + return new ArrayList<>(petList); + } + + public BookingResponse checkIn(Pet pet) { + CheckInStrategy checkInStrategy = CHECK_IN_STRATEGY .get(checkInStrategy()); + return checkInStrategy.doCheckIn(pet); + } + + private HotelAvailability checkInStrategy() { + return petList.size() petsOnWaiting; + + WaitingListStrategy(Collection pets){ + this.petsOnWaiting = pets; + } + + @Override + public BookingResponse doCheckIn(Pet pet) { + petsOnWaiting.add(pet); + return BookingResponse.waitingListFor(pet); + } +} diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java b/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java index 8d4d40fa..77aae38a 100644 --- a/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java +++ b/src/main/java/serenitylabs/tutorials/vetclinic/Pet.java @@ -2,7 +2,7 @@ import com.google.common.base.Objects; -public class Pet { +public class Pet implements Comparable{ private final String name; private final Breed breed; @@ -25,6 +25,11 @@ public Breed getBreed() { public static PetBuilder parrot() { return new PetBuilder(Breed.Parrot);} public static PetBuilder fish() { return new PetBuilder(Breed.Fish);} + @Override + public int compareTo(String o) { + return 0; + } + public static class PetBuilder { private final Breed breed; diff --git a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java index 6a5c242b..f78f9a22 100644 --- a/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java +++ b/src/main/java/serenitylabs/tutorials/vetclinic/collections/katas/APetHotel.java @@ -1,6 +1,7 @@ package serenitylabs.tutorials.vetclinic.collections.katas; import com.google.common.collect.ImmutableList; +import domain.PetHotel; import serenitylabs.tutorials.vetclinic.Breed; import serenitylabs.tutorials.vetclinic.Pet; @@ -23,7 +24,7 @@ public PetAdder(int petCount) { this.petCount = petCount; } - private Pet somePet(int petCount) { + public Pet somePet(int petCount) { return new Pet(someName(petCount), someBreed()); } @@ -38,5 +39,13 @@ private Breed someBreed() { private String someName(int petCount) { return PET_NAMES.get(random.nextInt(PET_NAMES.size())) + " " + petCount; } + + public PetHotel petsCheckedIn() { + PetHotel hotel = new PetHotel(); + for(int count = 0; count < petCount; count++) { + hotel.checkIn(somePet(count)); + } + return hotel; + } } } diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java index 5486b552..96fdfa65 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java @@ -1,45 +1,135 @@ package serenitylabs.tutorials.vetclinic.collections.katas; +import domain.*; +import org.junit.Before; import org.junit.Test; +import serenitylabs.tutorials.vetclinic.Pet; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class WhenBookingPetsIntoAPetHotel { + private PetHotel petHotel; + @Before + public void initialize_pet_hotel(){ + petHotel = new PetHotel(); + } @Test public void the_hotel_should_initially_have_no_pets_booked() { + + assertThat(petHotel.getPets().size(),equalTo(0)); } @Test public void should_be_able_to_check_a_pet_into_the_hotel() throws Exception { + Pet fido = Pet.dog().named("Fido"); + petHotel.checkIn(fido); + + assertThat(petHotel.getPets(),contains(fido)); } @Test public void should_be_able_to_check_in_several_pets() throws Exception { + Pet fido = Pet.dog().named("Fido"); + Pet felix = Pet.cat().named("Felix"); + Pet roger = Pet.dog().named("Roger"); + Pet siemens = Pet.cat().named("Siemens"); + + petHotel.checkIn(fido); + petHotel.checkIn(felix); + petHotel.checkIn(roger); + petHotel.checkIn(siemens); + + assertThat(petHotel.getPets().size(),equalTo(4)); + assertThat(petHotel.getPets(),containsInAnyOrder(fido,felix,roger,siemens)); } @Test public void should_not_be_able_to_check_in_the_same_pet_twice() throws Exception { + Pet roger = Pet.dog().named("Roger"); + + petHotel.checkIn(roger); + petHotel.checkIn(roger); + + assertThat(petHotel.getPets().size(),equalTo(1)); } @Test public void should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order() throws Exception { + //GIVEN + Pet fido = Pet.dog().named("E"); + Pet felix = Pet.cat().named("Z"); + Pet roger = Pet.dog().named("A"); + Pet siemens = Pet.cat().named("D"); + + //WHEN + + petHotel.checkIn(fido); + petHotel.checkIn(felix); + petHotel.checkIn(roger); + petHotel.checkIn(siemens); + + //THEN + //TODO + assertThat(petHotel.getPets(),contains(roger,siemens,fido,felix)); } @Test public void should_be_able_to_obtain_a_booking_confirmation_when_we_check_in_a_pet() throws Exception { + + //GIVEN + Pet fido = Pet.dog().named("Fido"); + + //WHEN + + BookingResponse bookingResponse = petHotel.checkIn(fido); + + //THEN + assertThat(bookingResponse.isConfirmed(),is(equalTo(true))); + } @Test public void should_not_be_able_to_check_in_pets_beyond_hotel_capacity() throws Exception { + //GIVEN + PetHotel petHotel = APetHotel.with(PetHotel.MAX_SIZE).petsCheckedIn(); + //WHEN + Pet fido = Pet.dog().named("Fido"); + BookingResponse bookingResponse = petHotel.checkIn(fido); + + //THEN + + assertThat(bookingResponse.isOnWaiting(),is(equalTo(true))); } @Test public void should_notify_owner_that_the_hotel_is_full() throws Exception { + //GIVEN + PetHotel petHotel = APetHotel.with(PetHotel.MAX_SIZE).petsCheckedIn(); + + //WHEN + Pet fido = Pet.dog().named("Fido"); + BookingResponse bookingResponse = petHotel.checkIn(fido); + + //THEN + + //assertThat(); } @Test public void should_place_pets_on_a_waiting_list_when_the_hotel_is_full() throws Exception { + //GIVEN + PetHotel petHotel = APetHotel.with(PetHotel.MAX_SIZE).petsCheckedIn(); + //WHEN + Pet fido = Pet.dog().named("Fido"); + BookingResponse bookingResponse = petHotel.checkIn(fido); + + //THEN + + assertThat(bookingResponse.isOnWaiting(),is(equalTo(true))); } @Test From 5173643f882ee5d64167c78bd3d1b8e65a75c0d5 Mon Sep 17 00:00:00 2001 From: pravyada Date: Tue, 20 Sep 2016 21:36:20 +0530 Subject: [PATCH 12/13] Code refactored --- .../collections/katas/WhenBookingPetsIntoAPetHotel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java index 96fdfa65..40cd0281 100644 --- a/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java +++ b/src/test/java/serenitylabs/tutorials/vetclinic/collections/katas/WhenBookingPetsIntoAPetHotel.java @@ -72,7 +72,6 @@ public void should_be_able_to_retrieve_checked_in_pets_in_alphabetical_order() t petHotel.checkIn(siemens); //THEN - //TODO assertThat(petHotel.getPets(),contains(roger,siemens,fido,felix)); } From 9df55d8796bf1c39f613a9abe706f5fe8c33778c Mon Sep 17 00:00:00 2001 From: pravyada Date: Wed, 21 Sep 2016 11:03:02 +0530 Subject: [PATCH 13/13] Pending test cases implemented --- src/main/java/domain/PetHotel.java | 3 ++ .../katas/WhenBookingPetsIntoAPetHotel.java | 40 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/PetHotel.java b/src/main/java/domain/PetHotel.java index 11b46b98..35fd09f8 100644 --- a/src/main/java/domain/PetHotel.java +++ b/src/main/java/domain/PetHotel.java @@ -40,4 +40,7 @@ public void checkOut(Pet pet){ } + public HotelAvailability getAvailablility() { + return petList.size()