Characterization Testing: Card¶
Characterization tests, sometimes called Approval tests, assume that the code works as desired, so any tests written can make that assumption as well. They often leverage textual output vs. the typical property/state testing we do in unit tests.
Goal¶
We want to extract the display methods in Card
into Game
, but it doesn't have good test coverage, so we'll need to write some tests before we refactor.
We're Done When...
We know we're done when there are we have removed all System.out.print
statements from the Card
class, as well as any "display" methods that return a String.
A. Characterize Ten Card Display¶
We'll start with the Card#display()
method. We know that the main difference in display behavior is for cards with a rank of 10 (because they take up two characters) and all other cards (which only take a single character), so we'll create two characterization tests.
-
Create a new test class called
CardDisplayTest
.package com.jitterted.ebp.blackjack; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; class CardDisplayTest { }
-
Create a test method
displayTenAsString
that creates a card with a Rank of 10, with any Suit, calls thedisplay()
method, and asserts that the result is equal to an empty String, e.g.:assertThat(display) .isEqualTo("");
When you run this test, it'll fail.
To make it pass, copy the "actual" result into the assertion and run it again. It should now pass. You now have characterized the behavior for Ten cards.
Watch out for ESCape Characters
Be careful when copying the actual result as there are ESC (escape) characters embedded in the output. In IntelliJ, you can use the
click to show difference
to show the hidden escape characters, which makes it easier to copy from.
B. Characterize Non-Ten Card¶
-
Create another test method
displayNonTenAsString
that creates a card with any non-ten Rank card. -
As above, assert that the display is an empty string, run the test and watch it fail.
-
Again, copy the actual output into the test and make sure it passes.
-
Make sure all other tests pass before moving on.
C. Refactor Card Display¶
Now that we have test coverage, let's move the console-based display code out of Card
and into a new ConsoleCard
class.
-
Create new public methods on
Card
for querying the Rank (viarank()
) and Suit (viasuit()
) and replace direct references to the instance variables in thedisplay()
method with these query methods. -
Use the refactoring "Make Static" to make the
display()
method inCard
become static. Have theCard
be passed in as a parameter. The result should look like:public static String display(Card card) {
-
Use the Move Static Members refactoring (F6 is the shortcut in IntelliJ IDEA) to move the display method to a new class:
ConsoleCard
.
Note
Make sure all the tests pass when you are done.
You are done!