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 onHand
that returns the firstCard
from the list.Want to learn to use Extract Method here? Click
>
You can do this via an Extract Method refactoring of the existing
displayFaceUpCard
method:- 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
public
access visibility
- Select
-
-
Refactor
displayFaceUpCard
to be a static method usingRefactor > Make Static...
. You will be presented with a parameter to pass in, which should behand
. ChooseRefactor
to continue. -
Move the method to a new class named
ConsoleHand
(in the samecom.r2ha.blackjack
package) by using theRefactor > Move Members
action, 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
String
on 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
public
query method (namedcards()
) on theHand
class that returns aList<Card>
, so that it will be accessible by thecardsAsString
method 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.println
reference 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 println
s and String
s? 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
.