diff --git a/solution/day17/docs/step-by-step.md b/solution/day17/docs/step-by-step.md index eb7c02b6..6d1aba17 100644 --- a/solution/day17/docs/step-by-step.md +++ b/solution/day17/docs/step-by-step.md @@ -63,17 +63,17 @@ We use the discoverability of the library to start implementing it. // A classic Unit Test @Test void returns_none_for_invalid_input(){ - Arbitrary invalidInput=Arbitrary.integer().filter(x->x< 1||x>100); - - // Define a property - Property.def("None for numbers out of range") - .forAll(invalidInput) - // Define the predicate - .suchThat(x->FizzBuzz.convert(x).isEmpty()) - .check() - // Necessary fo asserting -> junit - .assertIsSatisfied(); - } + Arbitrary invalidInput=Arbitrary.integer().filter(x->x< 1||x>100); + + // Define a property + Property.def("None for numbers out of range") + .forAll(invalidInput) + // Define the predicate + .suchThat(x->FizzBuzz.convert(x).isEmpty()) + .check() + // Necessary fo asserting -> junit + .assertIsSatisfied(); +} ``` - Our property is green @@ -91,31 +91,31 @@ void returns_none_for_invalid_input(){ ```java @Test void parse_fail_for_numbers_out_of_range(){ - def("None for numbers out of range") + def("None for numbers out of range") .forAll(integer().filter(x->xMAX)) .suchThat(x->FizzBuzz.convert(x).isEmpty()) .check() .assertIsSatisfied(); - } +} ``` - We can now delete the `non passing` test (it is covered by our property) ```java public static Stream invalidInputs(){ - return Stream.of( + return Stream.of( Arguments.of(0), Arguments.of(-1), Arguments.of(101) - ); - } + ); +} @ParameterizedTest @MethodSource("invalidInputs") void parse_fail_for_numbers_out_of_range(int input){ - assertThat(FizzBuzz.convert(input).isEmpty()) - .isTrue(); - } + assertThat(FizzBuzz.convert(input).isEmpty()) + .isTrue(); +} ``` ### Write the "valid" property @@ -125,51 +125,79 @@ void parse_fail_for_numbers_out_of_range(int input){ ```java @Test void parse_return_valid_string_for_numbers_between_1_and_100(){ - def("Some(validString) for numbers in [1; 100]") - .forAll(integer().filter(x->x>=MIN&&x<=MAX)) - .suchThat(x->FizzBuzz.convert(x).exists(s->Seq("Fizz","Buzz","FizzBuzz",x.toString()).contains(s))) - .check() - .assertIsSatisfied(); - } + def("Some(validString) for numbers in [1; 100]") + .forAll(integer().filter(x->x>=MIN&&x<=MAX)) + .suchThat(x->FizzBuzz.convert(x).exists(s->Seq("Fizz","Buzz","FizzBuzz",x.toString()).contains(s))) + .check() + .assertIsSatisfied(); +} ``` - Let's refactor it to make it simpler to understand ```java -@Test -void parse_return_valid_string_for_numbers_between_1_and_100(){ - def("Some(validString) for numbers in [1; 100]") - .forAll(validInput()) - .suchThat(this::isConvertValid) - .check() - .assertIsSatisfied(); - } +class FizzBuzzTests { + private static final Seq fizzBuzzStrings = List("Fizz", "Buzz", "FizzBuzz"); -private static Arbitrary validInput(){ - return integer().filter(x->x>MIN&&x<=MAX); - } + public static Stream validInputs() { + return Stream.of( + Arguments.of(1, "1"), + Arguments.of(67, "67"), + Arguments.of(82, "82"), + Arguments.of(3, "Fizz"), + Arguments.of(66, "Fizz"), + Arguments.of(99, "Fizz"), + Arguments.of(5, "Buzz"), + Arguments.of(50, "Buzz"), + Arguments.of(85, "Buzz"), + Arguments.of(15, "FizzBuzz"), + Arguments.of(30, "FizzBuzz"), + Arguments.of(45, "FizzBuzz") + ); + } -private boolean isConvertValid(Integer x){ + @ParameterizedTest + @MethodSource("validInputs") + void parse_successfully_numbers_between_1_and_100_samples(int input, String expectedResult) { + assertThat(FizzBuzz.convert(input)) + .isEqualTo(Some(expectedResult)); + } + + @Test + void parse_return_valid_string_for_numbers_between_1_and_100() { + def("Some(validString) for numbers in [1; 100]") + .forAll(validInput()) + .suchThat(this::isConvertValid) + .check() + .assertIsSatisfied(); + } + + @Test + void parse_fail_for_numbers_out_of_range() { + def("None for numbers out of range") + .forAll(invalidInput()) + .suchThat(x -> FizzBuzz.convert(x).isEmpty()) + .check() + .assertIsSatisfied(); + } + + private boolean isConvertValid(Integer x) { return FizzBuzz.convert(x) - .exists(s->validStringsFor(x).contains(s)); - } + .exists(s -> validStringsFor(x).contains(s)); + } -private static Seq validStringsFor(Integer x){ - return fizzBuzzStrings.append(x.toString()); - } + private static Arbitrary validInput() { + return integer().filter(x -> x >= MIN && x <= MAX); + } -@Test -void parse_fail_for_numbers_out_of_range(){ - def("None for numbers out of range") - .forAll(invalidInput()) - .suchThat(x->FizzBuzz.convert(x).isEmpty()) - .check() - .assertIsSatisfied(); - } + private static Seq validStringsFor(Integer x) { + return fizzBuzzStrings.append(x.toString()); + } -private static Arbitrary invalidInput(){ - return integer().filter(x->xMAX); - } + private static Arbitrary invalidInput() { + return integer().filter(x -> x < MIN || x > MAX); + } +} ``` We won't remove the test `parse_successfully_numbers_between_1_and_100_samples`, why? \ No newline at end of file