From a28010cd571311a83b2d98404f22cc71f3e3bcbf Mon Sep 17 00:00:00 2001 From: Smarticles101 Date: Thu, 22 Jun 2017 15:20:43 -0500 Subject: [PATCH 1/6] two-fer: dibs on implementing From ebb05f74e9f07efa84f1ee9d435b1527e10a0a04 Mon Sep 17 00:00:00 2001 From: Smarticles101 Date: Thu, 22 Jun 2017 21:32:56 -0500 Subject: [PATCH 2/6] implemented exercise two-fer --- config.json | 5 +++ exercises/settings.gradle | 1 + exercises/two-fer/build.gradle | 17 ++++++++ .../two-fer/src/example/java/Twofer.java | 5 +++ exercises/two-fer/src/main/java/Twofer.java | 5 +++ .../two-fer/src/test/java/TwoferTest.java | 41 +++++++++++++++++++ 6 files changed, 74 insertions(+) create mode 100644 exercises/two-fer/build.gradle create mode 100644 exercises/two-fer/src/example/java/Twofer.java create mode 100644 exercises/two-fer/src/main/java/Twofer.java create mode 100644 exercises/two-fer/src/test/java/TwoferTest.java diff --git a/config.json b/config.json index f9fd03235..3cdb75b68 100644 --- a/config.json +++ b/config.json @@ -10,6 +10,11 @@ "difficulty": 1, "topics": [] }, + { + "slug": "two-fer", + "difficulty": 1, + "topics": [] + }, { "slug": "rna-transcription", "difficulty": 2, diff --git a/exercises/settings.gradle b/exercises/settings.gradle index 15562c812..ed4e02a44 100644 --- a/exercises/settings.gradle +++ b/exercises/settings.gradle @@ -67,5 +67,6 @@ include 'sum-of-multiples' include 'triangle' include 'trinary' include 'twelve-days' +include 'two-fer' include 'word-count' include 'wordy' diff --git a/exercises/two-fer/build.gradle b/exercises/two-fer/build.gradle new file mode 100644 index 000000000..d019b23c7 --- /dev/null +++ b/exercises/two-fer/build.gradle @@ -0,0 +1,17 @@ +apply plugin: "java" +apply plugin: "eclipse" +apply plugin: "idea" + +repositories { + mavenCentral() +} + +dependencies { + testCompile "junit:junit:4.12" +} +test { + testLogging { + exceptionFormat = 'full' + events = ["passed", "failed", "skipped"] + } +} diff --git a/exercises/two-fer/src/example/java/Twofer.java b/exercises/two-fer/src/example/java/Twofer.java new file mode 100644 index 000000000..5947535bf --- /dev/null +++ b/exercises/two-fer/src/example/java/Twofer.java @@ -0,0 +1,5 @@ +public class Twofer { + public String twofer(String name) { + return "One for " + (name != null ? name : "you") + ", one for me."; + } +} \ No newline at end of file diff --git a/exercises/two-fer/src/main/java/Twofer.java b/exercises/two-fer/src/main/java/Twofer.java new file mode 100644 index 000000000..eeedaed9b --- /dev/null +++ b/exercises/two-fer/src/main/java/Twofer.java @@ -0,0 +1,5 @@ +public class Twofer { + public String twofer(String name) { + throw new UnsupportedOperationException("Delete this statement and write your own implementation."); + } +} \ No newline at end of file diff --git a/exercises/two-fer/src/test/java/TwoferTest.java b/exercises/two-fer/src/test/java/TwoferTest.java new file mode 100644 index 000000000..09c0ea0ca --- /dev/null +++ b/exercises/two-fer/src/test/java/TwoferTest.java @@ -0,0 +1,41 @@ +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class TwoferTest { + + private Twofer twofer; + + @Before + public void setup() { + twofer = new Twofer(); + } + + @Test + public void noNameGiven() { + String input = null; + String expected = "One for you, one for me."; + + assertEquals(expected, twofer.twofer(input)); + } + + @Test + @Ignore("Remove to run test") + public void aNameGiven() { + String input = "Alice"; + String expected = "One for Alice, one for me."; + + assertEquals(expected, twofer.twofer(input)); + } + + @Test + @Ignore("Remove to run test") + public void anotherNameGiven() { + String input = "Bob"; + String expected = "One for Bob, one for me."; + + assertEquals(expected, twofer.twofer(input)); + } +} \ No newline at end of file From 631b0bf5a5e65a054a3d40ea5a940c89cc67348b Mon Sep 17 00:00:00 2001 From: Smarticles101 Date: Sat, 24 Jun 2017 15:25:42 -0500 Subject: [PATCH 3/6] Remove `@Ignore` annotations from hello-world, to be introduced in two-fer --- exercises/hello-world/GETTING_STARTED.md | 3 +- exercises/hello-world/TUTORIAL.md | 271 ++++++++---------- .../src/test/java/HelloWorldTest.java | 4 - 3 files changed, 119 insertions(+), 159 deletions(-) diff --git a/exercises/hello-world/GETTING_STARTED.md b/exercises/hello-world/GETTING_STARTED.md index d1463deb7..7ce6023d0 100644 --- a/exercises/hello-world/GETTING_STARTED.md +++ b/exercises/hello-world/GETTING_STARTED.md @@ -20,8 +20,7 @@ $ gradle test ## Iterate through the tests -After your first test passes, remove the `@Ignore` from the next test, and iterate on your solution, -testing after each change. +After your first test passes, iterate on your solution, testing after each change. ## All the tests pass? Submit your solution! diff --git a/exercises/hello-world/TUTORIAL.md b/exercises/hello-world/TUTORIAL.md index d4c298b63..ccb5d4d22 100644 --- a/exercises/hello-world/TUTORIAL.md +++ b/exercises/hello-world/TUTORIAL.md @@ -74,72 +74,104 @@ running the task you asked it to: executing the tests against the solution. ``` :test +HelloWorldTest > helloSampleName FAILED + java.lang.UnsupportedOperationException: Delete this statement and write your own implementation. + at HelloWorld.hello(HelloWorld.java:3) + at HelloWorldTest.helloSampleName(HelloWorldTest.java:22) + HelloWorldTest > helloNoName FAILED - java.lang.AssertionError: expected: but was: - at org.junit.Assert.fail(Assert.java:93) - at org.junit.Assert.failNotEquals(Assert.java:647) - at org.junit.Assert.assertEquals(Assert.java:128) - at org.junit.Assert.assertEquals(Assert.java:147) - at HelloWorldTest.helloNoName(HelloWorldTest.java:10) + java.lang.UnsupportedOperationException: Delete this statement and write your own implementation. + at HelloWorld.hello(HelloWorld.java:3) + at HelloWorldTest.helloNoName(HelloWorldTest.java:11) -HelloWorldTest > helloSampleName SKIPPED +HelloWorldTest > emptyStringIsComparedByValue FAILED + java.lang.UnsupportedOperationException: Delete this statement and write your own implementation. + at HelloWorld.hello(HelloWorld.java:3) + at HelloWorldTest.emptyStringIsComparedByValue(HelloWorldTest.java:17) -HelloWorldTest > helloAnotherSampleName SKIPPED +HelloWorldTest > helloAnotherSampleName FAILED + java.lang.UnsupportedOperationException: Delete this statement and write your own implementation. + at HelloWorld.hello(HelloWorld.java:3) + at HelloWorldTest.helloAnotherSampleName(HelloWorldTest.java:27) -3 tests completed, 1 failed, 2 skipped +4 tests completed, 4 failed :test FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':test'. -> There were failing tests. See the report at: file:///Users/jtigger/projects/exercism/xjava/build/exercism/java/hello-world/build/reports/tests/index.html +> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD FAILED -Total time: 6.716 secs +Total time: 12.361 secs ``` Seeing the word "fail" TEN TIMES might give you the impression you've done something horribly wrong. You haven't. It's a whole lot of noise over -a single test not passing. +a few tests not passing. Let's focus in on the important bits: ``` -HelloWorldTest > helloNoName FAILED - java.lang.AssertionError: expected: but was: +HelloWorldTest > helloSampleName FAILED + java.lang.UnsupportedOperationException: Delete this statement and write your own implementation. ``` ...is read: "Within the test class named `HelloWorldTest`, the test method -`helloNoName` did not pass because the solution did not satisfy an -assertion. Apparently, we expected to see the string 'Hello, World!' but -the value `null` was returned instead. +`helloSampleName` did not pass because an `UnsupportedOperationException` was thrown with the message +`Delete this statement and write your own implementation.`." -The last line of the stack trace tells us exactly where this unsatisfied -assertion lives: +The next line of the stack trace tells us where the exception was thrown: ``` - at HelloWorldTest.helloNoName(HelloWorldTest.java:10) + at HelloWorld.hello(HelloWorld.java:3) ``` +Looks like it was on line 3 in the HelloWorld file. + +We should remove this line from our `HelloWorld.java` file. + +In your favorite text editor, open `src/main/java/HelloWorld.java`. + +Delete the contents of that line and replace it with the following: +```java +return null; +``` +Now you can run `gradle test` again. + +You should see a new error this time, don't worry though, you're making progress. + +``` +HelloWorldTest > helloNoName FAILED + java.lang.AssertionError: expected: but was: +``` +...is read: "Within the test class named HelloWorldTest, +the test method helloNoName did not pass because the solution did not satisfy an assertion. +Apparently, we expected to see the string 'Hello, World!' but the value null was returned instead. + +The last line of the stack trace tells us exactly where this unsatisfied assertion lives: + +``` + at HelloWorldTest.helloNoName(HelloWorldTest.java:10) +``` Looks like the crime was discovered on line 10 in the test file. Knowing these two facts, -1. the return value was not what was expected, and -2. the failure was on line 10 of the test, - -we can turn this failure into success. +1. The return value was not what was expected, and +2. The failure was on line 10 of the test, +We can turn this failure into success. -## Fixing the first failing test +## Fixing the first test -In your favorite text editor, open `src/test/java/HelloWorldTest.java` +Open `src/test/java/HelloWorldTest.java` and go to line 10. ```java @@ -182,88 +214,50 @@ $ gradle test :testClasses :test -HelloWorldTest > helloAnotherSampleName SKIPPED +HelloWorldTest > helloSampleName FAILED + org.junit.ComparisonFailure: expected: but was: + at org.junit.Assert.assertEquals(Assert.java:115) + at org.junit.Assert.assertEquals(Assert.java:144) + at HelloWorldTest.helloSampleName(HelloWorldTest.java:22) HelloWorldTest > helloNoName PASSED -HelloWorldTest > helloSampleName SKIPPED - -BUILD SUCCESSFUL +HelloWorldTest > emptyStringIsComparedByValue PASSED -Total time: 4.523 secs -``` - -"BUILD SUCCESSFUL"! Woohoo! :) You can see that `helloNoName()` test is -now passing. +HelloWorldTest > helloAnotherSampleName FAILED + org.junit.ComparisonFailure: expected: but was: + at org.junit.Assert.assertEquals(Assert.java:115) + at org.junit.Assert.assertEquals(Assert.java:144) + at HelloWorldTest.helloAnotherSampleName(HelloWorldTest.java:27) -With one win under our belt, we can turn our focus to some other messages -that we've been ignoring: the lines ending in "`SKIPPED`". - -Each test suite contains a series of tests, all of which have been marked -to be skipped/ignored except the first one. We did this to help you focus -on getting one test running at a time. - -Let's tackle the next test... - - - -## Enabling and fixing the second test +4 tests completed, 2 failed +:test FAILED -Right now, that second test is being skipped/ignored. Let's enable it. +FAILURE: Build failed with an exception. -(Re)open `src/test/java/HelloWorldTest.java` and find the second test: +* What went wrong: +Execution failed for task ':test'. +> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html -```java -... -@Test -@Ignore -public void helloSampleName() { - assertEquals("Hello, Alice!", HelloWorld.hello("Alice")); -} -... -``` +* Try: +Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. -When the JUnit test runner sees that `@Ignore` annotation on the test -method, it knows to skip over that test. Remove that line: +BUILD FAILED -```java -... -@Test -public void helloSampleName() { - assertEquals("Hello, Alice!", HelloWorld.hello("Alice")); -} -... +Total time: 20.855 secs ``` -Now, when you run the tests, both tests run: - -```sh -$ gradle test -... -:test - -HelloWorldTest > helloNoName PASSED +Woohoo! :) You can see that `helloNoName()` and `emptyStringIsComparedByValue()` are +now passing. -HelloWorldTest > helloSampleName FAILED - org.junit.ComparisonFailure: expected: but was: - at org.junit.Assert.assertEquals(Assert.java:125) - at org.junit.Assert.assertEquals(Assert.java:147) - at HelloWorldTest.helloSampleName(HelloWorldTest.java:16) +Let's tackle the next test... -HelloWorldTest > helloAnotherSampleName SKIPPED -3 tests completed, 1 failed, 1 skipped -... -``` -The first test, `helloNoName()` continues to pass. We see that -`helloSampleName` -- the test we just un-`@Ignore`'d -- is now running and -failing. Yay, failing test! In fact, the "failure" message is just -describing the difference between what the program does now and what it -should do for us to call it "done." +## Fixing the second test -Right now, we've hardcoded the greeting. Enabling this second test has -unleashed a new expectation: that our program incorporate a name given +Right now, we've hardcoded the greeting. This second test has +unleashed a new expectation: that our program must incorporate a name given into that greeting. When given the name "`Alice`", that's who should be greeted instead of "`World`". @@ -295,23 +289,43 @@ public class HelloWorld { $ gradle test :test -HelloWorldTest > helloAnotherSampleName SKIPPED +HelloWorldTest > helloSampleName PASSED HelloWorldTest > helloNoName FAILED org.junit.ComparisonFailure: expected: but was: - at org.junit.Assert.assertEquals(Assert.java:125) - at org.junit.Assert.assertEquals(Assert.java:147) - at HelloWorldTest.helloNoName(HelloWorldTest.java:10) + at org.junit.Assert.assertEquals(Assert.java:115) + at org.junit.Assert.assertEquals(Assert.java:144) + at HelloWorldTest.helloNoName(HelloWorldTest.java:11) -HelloWorldTest > helloSampleName PASSED +HelloWorldTest > emptyStringIsComparedByValue FAILED + org.junit.ComparisonFailure: expected: but was: + at org.junit.Assert.assertEquals(Assert.java:115) + at org.junit.Assert.assertEquals(Assert.java:144) + at HelloWorldTest.emptyStringIsComparedByValue(HelloWorldTest.java:17) -3 tests completed, 1 failed, 1 skipped +HelloWorldTest > helloAnotherSampleName PASSED + +4 tests completed, 2 failed +:test FAILED + +FAILURE: Build failed with an exception. + +* What went wrong: +Execution failed for task ':test'. +> There were failing tests. See the report at: file:///home/logan/hello-world/build/reports/tests/index.html + +* Try: +Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. + +BUILD FAILED + +Total time: 12.466 secs ``` Wait... didn't we just fix the test? Why is it failing? Take a closer look... In fact, `helloSampleName()` *is* passing. It's just that at the same time, -we just inadvertently broke that first test: `helloNoName()`. +we just inadvertently broke the first tests: `helloNoName()` and `emptyStringIsComparedByValue()`. This is one tiny example of the benefit of maintaining a test suite: if we use them to drive out our code, the second we break the program the tests @@ -319,7 +333,7 @@ say so. Since we saw them passing just *before* our latest change, whatever we *just* did most likely cause that regression. Our latest change was making the greeting dependent on the name given. Our -first test expects that if either a blank string or null are given as the +first two tests expects that if either a blank string or null are given as the name, then "`World`" should be substituted in. Let's implement that. `src/main/java/HelloWorld.java`: @@ -341,68 +355,17 @@ $ gradle test ... :test -HelloWorldTest > helloNoName PASSED - HelloWorldTest > helloSampleName PASSED -HelloWorldTest > helloAnotherSampleName SKIPPED - -BUILD SUCCESSFUL - -Total time: 4.804 secs -``` - -Excellent! We're now (at least) two-thirds the way done. Just one more -test to go... - - - -## Enabling the last test - -(Re)open `src/test/java/HelloWorldTest.java` and find the last test: - -```java -... -@Test -@Ignore -public void helloAnotherSampleName() { - assertEquals("Hello, Bob!", HelloWorld.hello("Bob")); -} -... -``` - -... and remove it's `@Ignore` to enable it ... - -```java -... -@Test -public void helloAnotherSampleName() { - assertEquals("Hello, Bob!", HelloWorld.hello("Bob")); -} -... -``` - -... and re-run the tests ... - -``` -$ gradle test -:compileJava UP-TO-DATE -:processResources UP-TO-DATE -:classes UP-TO-DATE -:compileTestJava -:processTestResources UP-TO-DATE -:testClasses -:test - HelloWorldTest > helloNoName PASSED -HelloWorldTest > helloSampleName PASSED +HelloWorldTest > emptyStringIsComparedByValue PASSED HelloWorldTest > helloAnotherSampleName PASSED BUILD SUCCESSFUL -Total time: 6.953 secs +Total time: 11.717 secs ``` Oh, hello! Turns out, the solution we put into place didn't just apply for @@ -476,9 +439,11 @@ We made a bunch of changes, let's make sure we didn't break the program! ``` $ gradle test ... +HelloWorldTest > helloSampleName PASSED + HelloWorldTest > helloNoName PASSED -HelloWorldTest > helloSampleName PASSED +HelloWorldTest > emptyStringIsComparedByValue PASSED HelloWorldTest > helloAnotherSampleName PASSED ... diff --git a/exercises/hello-world/src/test/java/HelloWorldTest.java b/exercises/hello-world/src/test/java/HelloWorldTest.java index d165bead1..1da655cba 100644 --- a/exercises/hello-world/src/test/java/HelloWorldTest.java +++ b/exercises/hello-world/src/test/java/HelloWorldTest.java @@ -5,7 +5,6 @@ public class HelloWorldTest { - @Test public void helloNoName() { assertEquals("Hello, World!", HelloWorld.hello("")); @@ -13,19 +12,16 @@ public void helloNoName() { } @Test - @Ignore public void emptyStringIsComparedByValue() { assertEquals("Hello, World!", HelloWorld.hello(new String(""))); } @Test - @Ignore public void helloSampleName() { assertEquals("Hello, Alice!", HelloWorld.hello("Alice")); } @Test - @Ignore public void helloAnotherSampleName() { assertEquals("Hello, Bob!", HelloWorld.hello("Bob")); } From 29b0d2d4c2428039839497c26da33c7eb5553292 Mon Sep 17 00:00:00 2001 From: Smarticles101 Date: Sat, 24 Jun 2017 15:34:57 -0500 Subject: [PATCH 4/6] Introduce `@Ignore`s in two-fer. --- exercises/two-fer/HINT.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 exercises/two-fer/HINT.md diff --git a/exercises/two-fer/HINT.md b/exercises/two-fer/HINT.md new file mode 100644 index 000000000..ef6c7bbc8 --- /dev/null +++ b/exercises/two-fer/HINT.md @@ -0,0 +1,3 @@ +To help you focus on one test at a time, [@Ignore](http://junit.sourceforge.net/javadoc/org/junit/Ignore.html) +annotations have been added to every test but the first one. Any test with an `@Ignore` annotation will be skipped +when you run the tests. \ No newline at end of file From 05a5c4fa343e691dccf8e701198e01e746456ba8 Mon Sep 17 00:00:00 2001 From: Logan Stucki Date: Sat, 24 Jun 2017 15:38:35 -0500 Subject: [PATCH 5/6] Remove explanation of `@Ignore` from hello-world --- exercises/hello-world/GETTING_STARTED.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/exercises/hello-world/GETTING_STARTED.md b/exercises/hello-world/GETTING_STARTED.md index c04949694..435d738b7 100644 --- a/exercises/hello-world/GETTING_STARTED.md +++ b/exercises/hello-world/GETTING_STARTED.md @@ -18,10 +18,6 @@ Try writing a solution that passes one test at a time, running Gradle each time: $ gradle test ``` -To help you focus on one test at a time, [@Ignore](http://junit.sourceforge.net/javadoc/org/junit/Ignore.html) -annotations have been added to every test but the first one. Any test with an `@Ignore` annotation will be skipped -when you run the tests. - ## Iterate through the tests After your first test passes, iterate on your solution, testing after each change. From 8ea73c2cc91eedf72ef210e35052a35319158654 Mon Sep 17 00:00:00 2001 From: Smarticles101 Date: Sat, 24 Jun 2017 17:31:28 -0500 Subject: [PATCH 6/6] Reformat two-fer in config --- config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 8113a8657..12c8be8e9 100644 --- a/config.json +++ b/config.json @@ -14,7 +14,9 @@ { "slug": "two-fer", "difficulty": 1, - "topics": [] + "topics": [ + + ] }, { "slug": "rna-transcription",