Characterization Testing: Hand¶
Do This First...
Be sure to have completed the prior labs before starting. You can also use the solution from the repository on GitHub and do a checkout of the tag lab2-start.
Goal¶
We'll continue characterizing and refactoring the display methods in the Hand class.
We're Done When...
We know we're done when we have removed all System.out.print statements from the Hand class, as well as any "display" methods that return a String.
A. Refactor Hand's Display Face Up Card¶
First, let's tackle the displayFaceUpCard method.
-
As you did in the previous lab, create a characterization test for
Hand.displayFaceUpCard()in a new test class (namedHandDisplayTest). You can copy and paste this test to start:Start With...
package com.r2ha.blackjack; import org.junit.jupiter.api.Test; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; public class HandDisplayTest { @Test void displayFaceUpCardReturnsAsCorrectString() throws Exception { List<Card> cards = List.of( new Card(Suit.HEARTS, Rank.ACE), new Card(Suit.CLUBS, Rank.JACK)); Hand hand = new Hand(cards); assertThat(hand.displayFaceUpCard()) .isEqualTo(""); } } -
For the refactor, the transformer class that we'll create (
ConsoleHand) will need to access the Face Up card so:-
Create a public
dealerFaceUpCard()query method onHandthat returns the firstCardfrom the list.Want to learn to use Extract Method here? Click
>You can do this via an Extract Method refactoring of the existing
displayFaceUpCardmethod:- Select
cards.get(0)only - Do
Refactor > Extract/Introduce > Method...or use the shortcut keys Cmd Option M (Mac) or Ctrl Alt M (Windows/Linux). - Name the new method
dealerFaceUpCard() - Ensure that the method has
publicaccess visibility
- Select
-
-
Refactor
displayFaceUpCardto be a static method usingRefactor > Make Static.... You will be presented with a parameter to pass in, which should behand. ChooseRefactorto continue. -
Move the method to a new class named
ConsoleHand(in the samecom.r2ha.blackjackpackage) by using theRefactor > Move Membersaction, or the F6 key.
Be sure to run the tests and make sure they all pass before continuing.
B. Repeat for Hand's Display¶
In this section, we'll move the method that displays the entire Hand's set of cards over to the ConsoleHand class.
-
Write a characterization test for Hand's
display()method. Since it doesn't return anything, you will have to refactor it to split it into two methods:-
One method that returns a
String(you can name itcardsAsString), do this with Extract Method. -
Another that displays that
Stringon the console usingSystem.out.println, this will bedisplay(), after the above method is extracted.Two Cards
Be sure to add two cards to the Hand for this test to ensure you capture the behavior of a two-card Hand.
-
-
Create a
publicquery method (namedcards()) on theHandclass that returns aList<Card>, so that it will be accessible by thecardsAsStringmethod after it's moved.Queries Don't Return Internal Information
Since we want to continue to encapsulate Hand's list, be sure to return a copy of the internal collection. We'll cover why in the walk-through of the solution.
-
Refactor the
cardsAsString()method to be static and then use the Move [Static] Members refactoring (F6) to move it toConsoleHand. -
Get rid of the
System.out.printlnreference in thedisplay()method by inlining that method (Cmd Option N on Mac, Ctrl Alt N on Windows) intoGame.- Yes, this just moves the "impurity" to another class, but we'll purify Game soon enough.
C. Complete "Purification" for Hand¶
Since displayValue() also returns a String that's meant for console output, we need to remove it to complete the purification of the Hand class. You will have to make the tradeoff between hiding the value() method, and purifying the class. Remember that pure domain outweighs the desire for encapsulation.
Once you remove the displayValue() method, and expose the value(), what tests might be changed to be easier to
work with?
Find them by searching for usages (Cmd B on Mac, Ctrl B on Windows). Update them as needed and make sure they still pass.
Are We Done?
Have we removed all printlns and Strings? If so, we're done.
Make sure all the tests pass before declaring your work complete!
You're Done
That's the end of this lab. Well done!
If you want to compare your solution with mine, you can checkout from the repository on GitHub using the tag lab2-solution.