Selaa lähdekoodia

Merge pull request #144 from exercism/quick-start-quide

Add quick start guide
John Ryan 10 vuotta sitten
vanhempi
commit
f33dd728dd
2 muutettua tiedostoa jossa 592 lisäystä ja 542 poistoa
  1. 16
    542
      exercises/hello-world/GETTING_STARTED.md
  2. 576
    0
      exercises/hello-world/TUTORIAL.md

+ 16
- 542
exercises/hello-world/GETTING_STARTED.md Näytä tiedosto

@@ -1,500 +1,29 @@
1
-NOTE: You can also view the HTML version of this file here:
2
-https://github.com/exercism/xjava/blob/master/exercises/hello-world/GETTING_STARTED.md
3
-
4
-* [Solving "Hello, World!"](#solving-hello-world)
5
- * [Reading Gradle output](#reading-gradle-output)
6
- * [Fixing the first failing test](#fixing-the-first-failing-test)
7
- * [Enabling and fixing the second test](#enabling-and-fixing-the-second-test)
8
- * [Enabling the last test](#enabling-the-last-test)
9
- * [Refactoring](#refactoring)
10
-* [Submitting your first iteration](#submitting-your-first-iteration)
11
-* [Next Steps](#next-steps)
12
- * [Review (and comment on) others' submissions to this exercise](#review-and-comment-on-others-submissions-to-this-exercise)
13
- * [Extend an exercise](#extend-an-exercise)
14
-
15
-----
16
-
17
-# Solving "Hello, World!"
18
-
19
-Welcome to the first exercise on the Java track!
20
-
21
-This is a step-by-step guide to solving this exercise.
22
-
23
-Each exercise comes with a set of tests.  The first pass through the
24
-exercise is about getting all of the tests to pass, one at a time.
25
-
26
-If you have not installed the Java Development Kit and Gradle, you must do
27
-so now.  For help with this, see: http://exercism.io/languages/java/installing
28
-
29 1
 ----
2
+# Quick Start Guide
30 3
 
31 4
 This guide picks-up where [Running the Tests (in Java)](http://exercism.io/languages/java/tests)
32 5
 left off.  If you haven't reviewed those instructions, do so now.
33 6
 
34
-The following instructions work equally well on Windows, Mac OS X and Linux.
35
-
36
-## Reading Gradle output
37
-
38
-Use Gradle to run the tests:
39
-
40
-```
41
-$ gradle test
42
-```
43
-
44
-This command does a lot and displays a bunch of stuff.  Let's break it down...
45
-
46
-```
47
-:compileJava
48
-:processResources UP-TO-DATE
49
-:classes
50
-```
51
-
52
-Each line that begins with a colon (like `:compileJava`) is Gradle telling
53
-us that it's starting that task.  The first three tasks are about compiling
54
-the source code of our *solution*. We've done you a favor and included just
55
-enough code for the solution that it compiles.
56
-
57
-When a task is successful, it generally does not output anything.  This is
58
-why `:compileJava` and `:classes` do not produce any additional output.
59
-`:processResources` reports that it had nothing to do.
60
-
61
-So far, so good...
62
-
63
-The next three tasks are about compiling source code of the *tests*.
64
-
65
-```
66
-:compileTestJava
67
-:processTestResources UP-TO-DATE
68
-:testClasses
69
-```
70
-
71
-... with both sets of source code successfully compiled, Gradle turns to
72
-running the task you asked it to: executing the tests against the solution.
73
-
74
-```
75
-:test
76
-
77
-HelloWorldTest > helloNoName FAILED
78
-    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
79
-        at org.junit.Assert.fail(Assert.java:93)
80
-        at org.junit.Assert.failNotEquals(Assert.java:647)
81
-        at org.junit.Assert.assertEquals(Assert.java:128)
82
-        at org.junit.Assert.assertEquals(Assert.java:147)
83
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
84
-
85
-HelloWorldTest > helloSampleName SKIPPED
86
-
87
-HelloWorldTest > helloAnotherSampleName SKIPPED
88
-
89
-3 tests completed, 1 failed, 2 skipped
90
-:test FAILED
91
-
92
-FAILURE: Build failed with an exception.
93
-
94
-* What went wrong:
95
-Execution failed for task ':test'.
96
-> There were failing tests. See the report at: file:///Users/jtigger/projects/exercism/xjava/build/exercism/java/hello-world/build/reports/tests/index.html
97
-
98
-* Try:
99
-Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
100
-
101
-BUILD FAILED
102
-
103
-Total time: 6.716 secs
104
-```
105
-
106
-Seeing the word "fail" TEN TIMES might give you the impression you've done
107
-something horribly wrong.  You haven't.  It's a whole lot of noise over
108
-a single test not passing.
109
-
110
-Let's focus in on the important bits:
111
-
112
-```
113
-HelloWorldTest > helloNoName FAILED
114
-    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
115
-```
116
-
117
-...is read: "Within the test class named `HelloWorldTest`, the test method
118
-`helloNoName` did not pass because the solution did not satisfy an
119
-assertion.  Apparently, we expected to see the string 'Hello, World!' but
120
-the value `null` was returned instead.
121
-
122
-The last line of the stack trace tells us exactly where this unsatisfied
123
-assertion lives:
124
-
125
-```
126
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
127
-```
128
-
129
-Looks like the crime was discovered on line 10 in the test file.
130
-
131
-Knowing these two facts,
132
-
133
-1. the return value was not what was expected, and
134
-2. the failure was on line 10 of the test,
135
- 
136
-we can turn this failure into success.
137
-
138
-
139
-
140
-## Fixing the first failing test
141
-
142
-In your favorite text editor, open `src/test/java/HelloWorldTest.java`
143
-and go to line 10.
144
-
145
-```java
146
-assertEquals("Hello, World!", HelloWorld.hello(""));
147
-```
148
-
149
-The test is expecting that `hello()`, when given an empty string (`""`),
150
-returns "Hello, World!".  Instead, `hello()` is returning `null`.
151
-Let's fix that.
152
-
153
-Open `src/main/java/HelloWorld.java`.
154
-
155
-```java
156
-public class HelloWorld {
157
-  public static String hello(String name) {
158
-    return null;
159
-  }
160
-}
161
-```
162
-
163
-Let's change that to return the expected string:
164
-
165
-```java
166
-public class HelloWorld {
167
-  public static String hello(String name) {
168
-    return "Hello, World!";
169
-  }
170
-}
171
-```
172
-
173
-Save the file and run the tests again:
174
-
175
-```
176
-$ gradle test
177
-:compileJava
178
-:processResources UP-TO-DATE
179
-:classes
180
-:compileTestJava
181
-:processTestResources UP-TO-DATE
182
-:testClasses
183
-:test
184
-
185
-HelloWorldTest > helloAnotherSampleName SKIPPED
186
-
187
-HelloWorldTest > helloNoName PASSED
188
-
189
-HelloWorldTest > helloSampleName SKIPPED
190
-
191
-BUILD SUCCESSFUL
192
-
193
-Total time: 4.523 secs
194
-```
195
-
196
-"BUILD SUCCESSFUL"!  Woohoo! :)  You can see that `helloNoName()` test is
197
-now passing.
198
-
199
-With one win under our belt, we can turn our focus to some other messages
200
-that we've been ignoring: the lines ending in "`SKIPPED`".
201
-
202
-Each test suite contains a series of tests, all of which have been marked
203
-to be skipped/ignored except the first one.  We did this to help you focus
204
-on getting one test running at a time.
205
-
206
-Let's tackle the next test...
207
-
208
-
209
-
210
-## Enabling and fixing the second test
211
-
212
-Right now, that second test is being skipped/ignored.  Let's enable it.
213
-
214
-(Re)open `src/test/java/HelloWorldTest.java` and find the second test:
215
-
216
-```java
217
-...
218
-@Test
219
-@Ignore
220
-public void helloSampleName() {
221
-  assertEquals("Hello, Alice!", HelloWorld.hello("Alice"));
222
-}
223
-...
224
-```
225
-
226
-When the JUnit test runner sees that `@Ignore` annotation on the test
227
-method, it knows to skip over that test.  Remove that line:
228
-
229
-```java
230
-...
231
-@Test
232
-public void helloSampleName() {
233
-  assertEquals("Hello, Alice!", HelloWorld.hello("Alice"));
234
-}
235
-...
236
-```
237
-
238
-Now, when you run the tests, both tests run:
239
-
240
-```sh
241
-$ gradle test
242
-...
243
-:test
244
-
245
-HelloWorldTest > helloNoName PASSED
246
-
247
-HelloWorldTest > helloSampleName FAILED
248
-    org.junit.ComparisonFailure: expected:<Hello, [Alice]!> but was:<Hello, [World]!>
249
-        at org.junit.Assert.assertEquals(Assert.java:125)
250
-        at org.junit.Assert.assertEquals(Assert.java:147)
251
-        at HelloWorldTest.helloSampleName(HelloWorldTest.java:16)
252
-
253
-HelloWorldTest > helloAnotherSampleName SKIPPED
254
-
255
-3 tests completed, 1 failed, 1 skipped
256
-...
257
-```
258
-
259
-The first test, `helloNoName()` continues to pass.  We see that
260
-`helloSampleName` -- the test we just un-`@Ignore`'d -- is now running and
261
-failing.  Yay, failing test!  In fact, the "failure" message is just
262
-describing the difference between what the program does now and what it
263
-should do for us to call it "done."
7
+Need more information?  A **step-by-step tutorial** is available in this directory at TUTORIAL.md or you can read 
8
+the [HTML version](https://github.com/exercism/xjava/blob/master/exercises/hello-world/TUTORIAL.md).
264 9
 
265
-Right now, we've hardcoded the greeting.  Enabling this second test has
266
-unleashed a new expectation: that our program incorporate a name given
267
-into that greeting.  When given the name "`Alice`", that's who should be
268
-greeted instead of "`World`".
269
-
270
-(Re)open `src/main/java/HelloWorld.java`.
271
-
272
-```java
273
-public class HelloWorld {
274
-  public static String hello(String name) {
275
-    return "Hello, World!";
276
-  }
277
-}
278
-```
279
-
280
-While `hello()` does accept a reference to a string named `name`, it is not
281
-using it in the output.  Let's change that:
282
-
283
-
284
-```java
285
-public class HelloWorld {
286
-  public static String hello(String name) {
287
-    return "Hello, " + name + "!";
288
-  }
289
-}
290
-```
291
-
292
-... and rerun the tests ...
293
-
294
-```
295
-$ gradle test
296
-:test
297
-
298
-HelloWorldTest > helloAnotherSampleName SKIPPED
299
-
300
-HelloWorldTest > helloNoName FAILED
301
-    org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, []!>
302
-        at org.junit.Assert.assertEquals(Assert.java:125)
303
-        at org.junit.Assert.assertEquals(Assert.java:147)
304
-        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
305
-
306
-HelloWorldTest > helloSampleName PASSED
307
-
308
-3 tests completed, 1 failed, 1 skipped
309
-```
310
-
311
-Wait... didn't we just fix the test?  Why is it failing?  Take a closer look...
312
-
313
-In fact, `helloSampleName()` *is* passing.  It's just that at the same time,
314
-we just inadvertently broke that first test: `helloNoName()`.
315
-
316
-This is one tiny example of the benefit of maintaining a test suite: if we
317
-use them to drive out our code, the second we break the program the tests
318
-say so.  Since we saw them passing just *before* our latest change,
319
-whatever we *just* did most likely cause that regression.
320
-
321
-Our latest change was making the greeting dependent on the name given. Our
322
-first test expects that if either a blank string or null are given as the
323
-name, then "`World`" should be substituted in.  Let's implement that.
324
-
325
-`src/main/java/HelloWorld.java`:
326
-```java
327
-public class HelloWorld {
328
-  public static String hello(String name) {
329
-    if(name == null || "".equals(name)) {
330
-      name = "World";
331
-    }
332
-    return "Hello, " + name + "!";
333
-  }
334
-}
335
-```
336
-
337
-... and re-run the tests ...
338
-
339
-```
340
-$ gradle test
341
-...
342
-:test
343
-
344
-HelloWorldTest > helloNoName PASSED
345
-
346
-HelloWorldTest > helloSampleName PASSED
347
-
348
-HelloWorldTest > helloAnotherSampleName SKIPPED
349
-
350
-BUILD SUCCESSFUL
351
-
352
-Total time: 4.804 secs
353
-```
354
-
355
-Excellent!  We're now (at least) two-thirds the way done.  Just one more
356
-test to go...
357
-
358
-
359
-
360
-## Enabling the last test
361
-
362
-(Re)open `src/test/java/HelloWorldTest.java` and find the last test:
363
-
364
-```java
365
-...
366
-@Test
367
-@Ignore
368
-public void helloAnotherSampleName() {
369
-    assertEquals("Hello, Bob!", HelloWorld.hello("Bob"));
370
-}
371
-...
372
-```
373
-
374
-... and remove it's `@Ignore` to enable it ...
375
-
376
-```java
377
-...
378
-@Test
379
-public void helloAnotherSampleName() {
380
-    assertEquals("Hello, Bob!", HelloWorld.hello("Bob"));
381
-}
382
-...
383
-```
384
-
385
-... and re-run the tests ...
386
-
387
-```
388
-$ gradle test
389
-:compileJava UP-TO-DATE
390
-:processResources UP-TO-DATE
391
-:classes UP-TO-DATE
392
-:compileTestJava
393
-:processTestResources UP-TO-DATE
394
-:testClasses
395
-:test
396
-
397
-HelloWorldTest > helloNoName PASSED
398
-
399
-HelloWorldTest > helloSampleName PASSED
400
-
401
-HelloWorldTest > helloAnotherSampleName PASSED
402
-
403
-BUILD SUCCESSFUL
404
-
405
-Total time: 6.953 secs
406
-```
407
-
408
-Oh, hello!  Turns out, the solution we put into place didn't just apply for
409
-"`Alice`" but "`Bob`" equally well.  In this case, the test succeeded with
410
-no additional code on our part.
411
-
412
-
413
-
414
-## Refactoring
415
-
416
-Now that you've got all the tests passing, you might consider whether
417
-the code is in the most readable/maintainable/efficient shape.  What makes
418
-for "good" design of software is a big topic.  The pursuit of it underlies
419
-much of what makes up the more valuable conversations on Exercism.
420
-
421
-For now, let's just take a quick review of our solution and see if there's
422
-any part of it we'd like to refactor.  Refactoring is changing the the way
423
-a bit of code reads without changing what it does.
424
-
425
-Right now, the details of detecting whether the caller of `hello()` has
426
-given a name or not (i.e. `name` is either `null` or an empty string) is
427
-sitting right next to the core responsibility of the method: to produce a
428
-personalized greeting.
429
-
430
-```java
431
-public class HelloWorld {
432
-  public static String hello(String name) {
433
-    if(name == null || "".equals(name)) {
434
-      name = "World";
435
-    }
436
-    return "Hello, " + name + "!";
437
-  }
438
-}
439
-```
440
-
441
-How would things read if we extracted those details into a separate method
442
-and at the same time, replaced the `if` with a ternary expression?
443
-
444
-```java
445
-public class HelloWorld {
446
-
447
-  public static String hello(String name) {
448
-    String whom = isBlank(name) ? "World" : name;
449
-    return "Hello, " + whom + "!";
450
-  }
451
-
452
-  private static boolean isBlank(String string) {
453
-    return string == null || "".equals(string);
454
-  }
455
-}
456
-```
457
-
458
-By extracting that logic into the `isBlank()` method, we've added a little
459
-abstraction to our program -- it's not as literal as it was before.  Yet,
460
-it allows us to defer *needing* to understand *how* "blankness" is
461
-detected.  If we can assume that `isBlank()` just works, we don't have to
462
-downshift in our head to those details.  Instead, we can remain at the same
463
-level of thinking: to whom are we greeting?
10
+The following instructions work equally well on Windows, Mac OS X and Linux.
464 11
 
465
-The ternary operator allowed us to express that choice in a more compact
466
-form.  Less to read without losing the intent.
12
+## Solve "Hello World"
467 13
 
468
-Finally, we introduced another variable: `whom`.  Doing so gives a name to
469
-the output of the ternary expression.  We certainly could have continued
470
-to reuse `name`, but by introducing a second `String` to hold the
471
-calculated value this keeps crisp the two ideas: `name` is what's given
472
-and `whom` is what's been determined.
14
+Try writing a solution that passes one test at a time, running Gradle each time:
473 15
 
474
-We made a bunch of changes, let's make sure we didn't break the program!
475 16
 
476 17
 ```
477 18
 $ gradle test
478
-...
479
-HelloWorldTest > helloNoName PASSED
480
-
481
-HelloWorldTest > helloSampleName PASSED
482
-
483
-HelloWorldTest > helloAnotherSampleName PASSED
484
-...
485 19
 ```
486 20
 
487
-This illustrates another benefit of writing tests: you can make significant
488
-changes to the structure of the program and very quickly restore your
489
-confidence that the program still works.  These tests are a far cry from a
490
-"proof" of correctness, but well-written tests do a much better job of
491
-(very quickly) giving us evidence that it is.  Without them, we manually
492
-run the program with different inputs and/or inspecting the code
493
-line-by-line -- time-consuming and error prone.
494
-
21
+## Iterate through the tests
495 22
 
23
+After your first test passes, remove the `@Ignore` from the next test, and ierate on your solution,
24
+testing after each change.
496 25
 
497
-# Submitting your first iteration
26
+## All the tests pass?  Submit your solution!
498 27
 
499 28
 With a working solution that we've reviewed, we're ready to submit it to
500 29
 exercism.io.
@@ -503,72 +32,17 @@ exercism.io.
503 32
 $ exercism submit src/main/java/HelloWorld.java
504 33
 ```
505 34
 
506
-
507
-
508
-# Next Steps
35
+## Next Steps
509 36
 
510 37
 From here, there are a number of paths you can take.
511 38
 
39
+1. Move on to the next exercise
40
+2. Review (and comment on) others' submissions to this exercise
41
+3. Submit another iteration
42
+4. Contribute to Exercism
512 43
 
513
-## Move on to the next exercise
514
-
515
-There are many more exercises you can practice with.  Grab the next one!
516
-
517
-```
518
-$ exercism fetch java
519
-```
520
-
521
-
522
-## Review (and comment on) others' submissions to this exercise
523
-
524
-The heart of Exercism are the conversations about coding
525
-practices.  It's definitely fun to practice, but engaging with others
526
-both in their attempts and your own is how you get feedback.  That feedback
527
-can help point out what you're doing well and where you might need to
528
-improve.
529
-
530
-Some submissions will be nearly identical to yours; others will be
531
-completely different.  Seeing both kinds can be instructive and interesting.
532
-
533
-Note that you can only view submissions of others for exercises you have
534
-completed yourself.  This enriches the experience of reading others' code
535
-because you'll have your own experience of trying to solve the problem.
536
-
537
-Here's an up-to-date list of submissions on the Java track:
538
-
539
-http://exercism.io/tracks/java/exercises
540
-
541
-
542
-
543
-## Submit another iteration
544
-
545
-You are also encouraged to consider additional "requirements" on a given
546
-exercise.
547
-
548
-For example, you could add a test or two that requires that the greeting
549
-use the capitalized form on the person's name, regardless of the case they
550
-used.
551
-
552
-In that situation, you'd write a test to set-up that new expectation and
553
-then implement that in the code (the same process we just went through
554
-together, above).
555
-
556
-
557
-
558
-## Contribute to Exercism
559
-
560
-The entire of Exercism is Open Source and is the labor of love for over
561
-100 maintainers and many more contributors.
562
-
563
-A starting point to jumping in can be found here:
564
-
565
-https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md
566
-
567
-
568
-----
569 44
 
570
-Regardless of what you decide to do next, we sincerely hope you learn
571
-and enjoy being part of this community.  If at any time you need assistance
45
+We sincerely hope you learn and enjoy being part of this community.  If at any time you need assistance
572 46
 do not hesitate to ask for help:
573 47
 
574 48
 http://exercism.io/languages/java/help

+ 576
- 0
exercises/hello-world/TUTORIAL.md Näytä tiedosto

@@ -0,0 +1,576 @@
1
+NOTE: You can also view the HTML version of this file here:
2
+https://github.com/exercism/xjava/blob/master/exercises/hello-world/TUTORIAL.md
3
+
4
+* [Solving "Hello, World!"](#solving-hello-world)
5
+ * [Reading Gradle output](#reading-gradle-output)
6
+ * [Fixing the first failing test](#fixing-the-first-failing-test)
7
+ * [Enabling and fixing the second test](#enabling-and-fixing-the-second-test)
8
+ * [Enabling the last test](#enabling-the-last-test)
9
+ * [Refactoring](#refactoring)
10
+* [Submitting your first iteration](#submitting-your-first-iteration)
11
+* [Next Steps](#next-steps)
12
+ * [Review (and comment on) others' submissions to this exercise](#review-and-comment-on-others-submissions-to-this-exercise)
13
+ * [Extend an exercise](#extend-an-exercise)
14
+
15
+----
16
+
17
+# Solving "Hello, World!"
18
+
19
+Welcome to the first exercise on the Java track!
20
+
21
+This is a step-by-step guide to solving this exercise.
22
+
23
+Each exercise comes with a set of tests.  The first pass through the
24
+exercise is about getting all of the tests to pass, one at a time.
25
+
26
+If you have not installed the Java Development Kit and Gradle, you must do
27
+so now.  For help with this, see: http://exercism.io/languages/java/installing
28
+
29
+----
30
+
31
+This guide picks-up where [Running the Tests (in Java)](http://exercism.io/languages/java/tests)
32
+left off.  If you haven't reviewed those instructions, do so now.
33
+
34
+The following instructions work equally well on Windows, Mac OS X and Linux.
35
+
36
+## Reading Gradle output
37
+
38
+Use Gradle to run the tests:
39
+
40
+```
41
+$ gradle test
42
+```
43
+
44
+This command does a lot and displays a bunch of stuff.  Let's break it down...
45
+
46
+```
47
+:compileJava
48
+:processResources UP-TO-DATE
49
+:classes
50
+```
51
+
52
+Each line that begins with a colon (like `:compileJava`) is Gradle telling
53
+us that it's starting that task.  The first three tasks are about compiling
54
+the source code of our *solution*. We've done you a favor and included just
55
+enough code for the solution that it compiles.
56
+
57
+When a task is successful, it generally does not output anything.  This is
58
+why `:compileJava` and `:classes` do not produce any additional output.
59
+`:processResources` reports that it had nothing to do.
60
+
61
+So far, so good...
62
+
63
+The next three tasks are about compiling source code of the *tests*.
64
+
65
+```
66
+:compileTestJava
67
+:processTestResources UP-TO-DATE
68
+:testClasses
69
+```
70
+
71
+... with both sets of source code successfully compiled, Gradle turns to
72
+running the task you asked it to: executing the tests against the solution.
73
+
74
+```
75
+:test
76
+
77
+HelloWorldTest > helloNoName FAILED
78
+    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
79
+        at org.junit.Assert.fail(Assert.java:93)
80
+        at org.junit.Assert.failNotEquals(Assert.java:647)
81
+        at org.junit.Assert.assertEquals(Assert.java:128)
82
+        at org.junit.Assert.assertEquals(Assert.java:147)
83
+        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
84
+
85
+HelloWorldTest > helloSampleName SKIPPED
86
+
87
+HelloWorldTest > helloAnotherSampleName SKIPPED
88
+
89
+3 tests completed, 1 failed, 2 skipped
90
+:test FAILED
91
+
92
+FAILURE: Build failed with an exception.
93
+
94
+* What went wrong:
95
+Execution failed for task ':test'.
96
+> There were failing tests. See the report at: file:///Users/jtigger/projects/exercism/xjava/build/exercism/java/hello-world/build/reports/tests/index.html
97
+
98
+* Try:
99
+Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
100
+
101
+BUILD FAILED
102
+
103
+Total time: 6.716 secs
104
+```
105
+
106
+Seeing the word "fail" TEN TIMES might give you the impression you've done
107
+something horribly wrong.  You haven't.  It's a whole lot of noise over
108
+a single test not passing.
109
+
110
+Let's focus in on the important bits:
111
+
112
+```
113
+HelloWorldTest > helloNoName FAILED
114
+    java.lang.AssertionError: expected:<Hello, World!> but was:<null>
115
+```
116
+
117
+...is read: "Within the test class named `HelloWorldTest`, the test method
118
+`helloNoName` did not pass because the solution did not satisfy an
119
+assertion.  Apparently, we expected to see the string 'Hello, World!' but
120
+the value `null` was returned instead.
121
+
122
+The last line of the stack trace tells us exactly where this unsatisfied
123
+assertion lives:
124
+
125
+```
126
+        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
127
+```
128
+
129
+Looks like the crime was discovered on line 10 in the test file.
130
+
131
+Knowing these two facts,
132
+
133
+1. the return value was not what was expected, and
134
+2. the failure was on line 10 of the test,
135
+ 
136
+we can turn this failure into success.
137
+
138
+
139
+
140
+## Fixing the first failing test
141
+
142
+In your favorite text editor, open `src/test/java/HelloWorldTest.java`
143
+and go to line 10.
144
+
145
+```java
146
+assertEquals("Hello, World!", HelloWorld.hello(""));
147
+```
148
+
149
+The test is expecting that `hello()`, when given an empty string (`""`),
150
+returns "Hello, World!".  Instead, `hello()` is returning `null`.
151
+Let's fix that.
152
+
153
+Open `src/main/java/HelloWorld.java`.
154
+
155
+```java
156
+public class HelloWorld {
157
+  public static String hello(String name) {
158
+    return null;
159
+  }
160
+}
161
+```
162
+
163
+Let's change that to return the expected string:
164
+
165
+```java
166
+public class HelloWorld {
167
+  public static String hello(String name) {
168
+    return "Hello, World!";
169
+  }
170
+}
171
+```
172
+
173
+Save the file and run the tests again:
174
+
175
+```
176
+$ gradle test
177
+:compileJava
178
+:processResources UP-TO-DATE
179
+:classes
180
+:compileTestJava
181
+:processTestResources UP-TO-DATE
182
+:testClasses
183
+:test
184
+
185
+HelloWorldTest > helloAnotherSampleName SKIPPED
186
+
187
+HelloWorldTest > helloNoName PASSED
188
+
189
+HelloWorldTest > helloSampleName SKIPPED
190
+
191
+BUILD SUCCESSFUL
192
+
193
+Total time: 4.523 secs
194
+```
195
+
196
+"BUILD SUCCESSFUL"!  Woohoo! :)  You can see that `helloNoName()` test is
197
+now passing.
198
+
199
+With one win under our belt, we can turn our focus to some other messages
200
+that we've been ignoring: the lines ending in "`SKIPPED`".
201
+
202
+Each test suite contains a series of tests, all of which have been marked
203
+to be skipped/ignored except the first one.  We did this to help you focus
204
+on getting one test running at a time.
205
+
206
+Let's tackle the next test...
207
+
208
+
209
+
210
+## Enabling and fixing the second test
211
+
212
+Right now, that second test is being skipped/ignored.  Let's enable it.
213
+
214
+(Re)open `src/test/java/HelloWorldTest.java` and find the second test:
215
+
216
+```java
217
+...
218
+@Test
219
+@Ignore
220
+public void helloSampleName() {
221
+  assertEquals("Hello, Alice!", HelloWorld.hello("Alice"));
222
+}
223
+...
224
+```
225
+
226
+When the JUnit test runner sees that `@Ignore` annotation on the test
227
+method, it knows to skip over that test.  Remove that line:
228
+
229
+```java
230
+...
231
+@Test
232
+public void helloSampleName() {
233
+  assertEquals("Hello, Alice!", HelloWorld.hello("Alice"));
234
+}
235
+...
236
+```
237
+
238
+Now, when you run the tests, both tests run:
239
+
240
+```sh
241
+$ gradle test
242
+...
243
+:test
244
+
245
+HelloWorldTest > helloNoName PASSED
246
+
247
+HelloWorldTest > helloSampleName FAILED
248
+    org.junit.ComparisonFailure: expected:<Hello, [Alice]!> but was:<Hello, [World]!>
249
+        at org.junit.Assert.assertEquals(Assert.java:125)
250
+        at org.junit.Assert.assertEquals(Assert.java:147)
251
+        at HelloWorldTest.helloSampleName(HelloWorldTest.java:16)
252
+
253
+HelloWorldTest > helloAnotherSampleName SKIPPED
254
+
255
+3 tests completed, 1 failed, 1 skipped
256
+...
257
+```
258
+
259
+The first test, `helloNoName()` continues to pass.  We see that
260
+`helloSampleName` -- the test we just un-`@Ignore`'d -- is now running and
261
+failing.  Yay, failing test!  In fact, the "failure" message is just
262
+describing the difference between what the program does now and what it
263
+should do for us to call it "done."
264
+
265
+Right now, we've hardcoded the greeting.  Enabling this second test has
266
+unleashed a new expectation: that our program incorporate a name given
267
+into that greeting.  When given the name "`Alice`", that's who should be
268
+greeted instead of "`World`".
269
+
270
+(Re)open `src/main/java/HelloWorld.java`.
271
+
272
+```java
273
+public class HelloWorld {
274
+  public static String hello(String name) {
275
+    return "Hello, World!";
276
+  }
277
+}
278
+```
279
+
280
+While `hello()` does accept a reference to a string named `name`, it is not
281
+using it in the output.  Let's change that:
282
+
283
+
284
+```java
285
+public class HelloWorld {
286
+  public static String hello(String name) {
287
+    return "Hello, " + name + "!";
288
+  }
289
+}
290
+```
291
+
292
+... and rerun the tests ...
293
+
294
+```
295
+$ gradle test
296
+:test
297
+
298
+HelloWorldTest > helloAnotherSampleName SKIPPED
299
+
300
+HelloWorldTest > helloNoName FAILED
301
+    org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, []!>
302
+        at org.junit.Assert.assertEquals(Assert.java:125)
303
+        at org.junit.Assert.assertEquals(Assert.java:147)
304
+        at HelloWorldTest.helloNoName(HelloWorldTest.java:10)
305
+
306
+HelloWorldTest > helloSampleName PASSED
307
+
308
+3 tests completed, 1 failed, 1 skipped
309
+```
310
+
311
+Wait... didn't we just fix the test?  Why is it failing?  Take a closer look...
312
+
313
+In fact, `helloSampleName()` *is* passing.  It's just that at the same time,
314
+we just inadvertently broke that first test: `helloNoName()`.
315
+
316
+This is one tiny example of the benefit of maintaining a test suite: if we
317
+use them to drive out our code, the second we break the program the tests
318
+say so.  Since we saw them passing just *before* our latest change,
319
+whatever we *just* did most likely cause that regression.
320
+
321
+Our latest change was making the greeting dependent on the name given. Our
322
+first test expects that if either a blank string or null are given as the
323
+name, then "`World`" should be substituted in.  Let's implement that.
324
+
325
+`src/main/java/HelloWorld.java`:
326
+```java
327
+public class HelloWorld {
328
+  public static String hello(String name) {
329
+    if(name == null || "".equals(name)) {
330
+      name = "World";
331
+    }
332
+    return "Hello, " + name + "!";
333
+  }
334
+}
335
+```
336
+
337
+... and re-run the tests ...
338
+
339
+```
340
+$ gradle test
341
+...
342
+:test
343
+
344
+HelloWorldTest > helloNoName PASSED
345
+
346
+HelloWorldTest > helloSampleName PASSED
347
+
348
+HelloWorldTest > helloAnotherSampleName SKIPPED
349
+
350
+BUILD SUCCESSFUL
351
+
352
+Total time: 4.804 secs
353
+```
354
+
355
+Excellent!  We're now (at least) two-thirds the way done.  Just one more
356
+test to go...
357
+
358
+
359
+
360
+## Enabling the last test
361
+
362
+(Re)open `src/test/java/HelloWorldTest.java` and find the last test:
363
+
364
+```java
365
+...
366
+@Test
367
+@Ignore
368
+public void helloAnotherSampleName() {
369
+    assertEquals("Hello, Bob!", HelloWorld.hello("Bob"));
370
+}
371
+...
372
+```
373
+
374
+... and remove it's `@Ignore` to enable it ...
375
+
376
+```java
377
+...
378
+@Test
379
+public void helloAnotherSampleName() {
380
+    assertEquals("Hello, Bob!", HelloWorld.hello("Bob"));
381
+}
382
+...
383
+```
384
+
385
+... and re-run the tests ...
386
+
387
+```
388
+$ gradle test
389
+:compileJava UP-TO-DATE
390
+:processResources UP-TO-DATE
391
+:classes UP-TO-DATE
392
+:compileTestJava
393
+:processTestResources UP-TO-DATE
394
+:testClasses
395
+:test
396
+
397
+HelloWorldTest > helloNoName PASSED
398
+
399
+HelloWorldTest > helloSampleName PASSED
400
+
401
+HelloWorldTest > helloAnotherSampleName PASSED
402
+
403
+BUILD SUCCESSFUL
404
+
405
+Total time: 6.953 secs
406
+```
407
+
408
+Oh, hello!  Turns out, the solution we put into place didn't just apply for
409
+"`Alice`" but "`Bob`" equally well.  In this case, the test succeeded with
410
+no additional code on our part.
411
+
412
+
413
+
414
+## Refactoring
415
+
416
+Now that you've got all the tests passing, you might consider whether
417
+the code is in the most readable/maintainable/efficient shape.  What makes
418
+for "good" design of software is a big topic.  The pursuit of it underlies
419
+much of what makes up the more valuable conversations on Exercism.
420
+
421
+For now, let's just take a quick review of our solution and see if there's
422
+any part of it we'd like to refactor.  Refactoring is changing the the way
423
+a bit of code reads without changing what it does.
424
+
425
+Right now, the details of detecting whether the caller of `hello()` has
426
+given a name or not (i.e. `name` is either `null` or an empty string) is
427
+sitting right next to the core responsibility of the method: to produce a
428
+personalized greeting.
429
+
430
+```java
431
+public class HelloWorld {
432
+  public static String hello(String name) {
433
+    if(name == null || "".equals(name)) {
434
+      name = "World";
435
+    }
436
+    return "Hello, " + name + "!";
437
+  }
438
+}
439
+```
440
+
441
+How would things read if we extracted those details into a separate method
442
+and at the same time, replaced the `if` with a ternary expression?
443
+
444
+```java
445
+public class HelloWorld {
446
+
447
+  public static String hello(String name) {
448
+    String whom = isBlank(name) ? "World" : name;
449
+    return "Hello, " + whom + "!";
450
+  }
451
+
452
+  private static boolean isBlank(String string) {
453
+    return string == null || "".equals(string);
454
+  }
455
+}
456
+```
457
+
458
+By extracting that logic into the `isBlank()` method, we've added a little
459
+abstraction to our program -- it's not as literal as it was before.  Yet,
460
+it allows us to defer *needing* to understand *how* "blankness" is
461
+detected.  If we can assume that `isBlank()` just works, we don't have to
462
+downshift in our head to those details.  Instead, we can remain at the same
463
+level of thinking: to whom are we greeting?
464
+
465
+The ternary operator allowed us to express that choice in a more compact
466
+form.  Less to read without losing the intent.
467
+
468
+Finally, we introduced another variable: `whom`.  Doing so gives a name to
469
+the output of the ternary expression.  We certainly could have continued
470
+to reuse `name`, but by introducing a second `String` to hold the
471
+calculated value this keeps crisp the two ideas: `name` is what's given
472
+and `whom` is what's been determined.
473
+
474
+We made a bunch of changes, let's make sure we didn't break the program!
475
+
476
+```
477
+$ gradle test
478
+...
479
+HelloWorldTest > helloNoName PASSED
480
+
481
+HelloWorldTest > helloSampleName PASSED
482
+
483
+HelloWorldTest > helloAnotherSampleName PASSED
484
+...
485
+```
486
+
487
+This illustrates another benefit of writing tests: you can make significant
488
+changes to the structure of the program and very quickly restore your
489
+confidence that the program still works.  These tests are a far cry from a
490
+"proof" of correctness, but well-written tests do a much better job of
491
+(very quickly) giving us evidence that it is.  Without them, we manually
492
+run the program with different inputs and/or inspecting the code
493
+line-by-line -- time-consuming and error prone.
494
+
495
+
496
+
497
+# Submitting your first iteration
498
+
499
+With a working solution that we've reviewed, we're ready to submit it to
500
+exercism.io.
501
+
502
+```
503
+$ exercism submit src/main/java/HelloWorld.java
504
+```
505
+
506
+
507
+
508
+# Next Steps
509
+
510
+From here, there are a number of paths you can take.
511
+
512
+
513
+## Move on to the next exercise
514
+
515
+There are many more exercises you can practice with.  Grab the next one!
516
+
517
+```
518
+$ exercism fetch java
519
+```
520
+
521
+
522
+## Review (and comment on) others' submissions to this exercise
523
+
524
+The heart of Exercism are the conversations about coding
525
+practices.  It's definitely fun to practice, but engaging with others
526
+both in their attempts and your own is how you get feedback.  That feedback
527
+can help point out what you're doing well and where you might need to
528
+improve.
529
+
530
+Some submissions will be nearly identical to yours; others will be
531
+completely different.  Seeing both kinds can be instructive and interesting.
532
+
533
+Note that you can only view submissions of others for exercises you have
534
+completed yourself.  This enriches the experience of reading others' code
535
+because you'll have your own experience of trying to solve the problem.
536
+
537
+Here's an up-to-date list of submissions on the Java track:
538
+
539
+http://exercism.io/tracks/java/exercises
540
+
541
+
542
+
543
+## Submit another iteration
544
+
545
+You are also encouraged to consider additional "requirements" on a given
546
+exercise.
547
+
548
+For example, you could add a test or two that requires that the greeting
549
+use the capitalized form on the person's name, regardless of the case they
550
+used.
551
+
552
+In that situation, you'd write a test to set-up that new expectation and
553
+then implement that in the code (the same process we just went through
554
+together, above).
555
+
556
+
557
+
558
+## Contribute to Exercism
559
+
560
+The entire of Exercism is Open Source and is the labor of love for over
561
+100 maintainers and many more contributors.
562
+
563
+A starting point to jumping in can be found here:
564
+
565
+https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md
566
+
567
+
568
+----
569
+
570
+Regardless of what you decide to do next, we sincerely hope you learn
571
+and enjoy being part of this community.  If at any time you need assistance
572
+do not hesitate to ask for help:
573
+
574
+http://exercism.io/languages/java/help
575
+
576
+Cheers!