Skip to content

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.

  1. 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 {
    }
    
  2. Create a test method displayTenAsString that creates a card with a Rank of 10, with any Suit, calls the display() 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

  1. Create another test method displayNonTenAsString that creates a card with any non-ten Rank card.

  2. As above, assert that the display is an empty string, run the test and watch it fail.

  3. Again, copy the actual output into the test and make sure it passes.

  4. 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.

  1. Create new public methods on Card for querying the Rank (via rank()) and Suit (via suit()) and replace direct references to the instance variables in the display() method with these query methods.

  2. Use the refactoring "Make Static" to make the display() method in Card become static. Have the Card be passed in as a parameter. The result should look like:

    public static String display(Card card) {
    
  3. 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!