Skip to content

Latest commit

 

History

History
300 lines (239 loc) · 12.2 KB

GettingStarted.md

File metadata and controls

300 lines (239 loc) · 12.2 KB

Contents

Getting Started

Parts of a Test

All tests (unit and otherwise) contain 2 parts:

  • Do
  • Verify

ApprovalTests is a way to handle the second part: Verification. All calls will look about the same:

Approvals.verify(objectToBeVerified);

snippet source | anchor

Strings

Letʼs say you wanted to test if a string was being built correctly:

@Test
public void testBuildString()
{
  /* Do */
  // create a string with "Approval" and append "Tests" to it
  String s = "Approval";
  s += " Tests";
  /* Verify */
  // Verify the resulting string
  Approvals.verify(s);
}

snippet source | anchor

Will Produce the following File:
GettingStartedTest.testBuildString.approved.txt

Containing

Approval Tests

snippet source | anchor

This is the 'actual result'.
The 'expected' result is in the file SampleTest.testBuildString.received.txt
(This is described in detail below.) When you see the results you want (“ApprovalTests”) as the result, simply Approve The Result.

Objects

Let's say that you wanted to test that a customized StringBuilder was creating text correctly:

@Test
public void testObject()
{
  /* Do */
  // create an 100 x 200 rectangle with the top corner at (5, 10)
  Rectangle objectUnderTest = new Rectangle(5, 10, 100, 200);
  /* Verify */
  // Verify the rectangle is properly defined
  Approvals.verify(objectUnderTest.toString());
}

snippet source | anchor

Will Produce the following File:
GettingStartedTest.testObject.approved.txt

Containing

java.awt.Rectangle[x=5,y=10,width=100,height=200]

snippet source | anchor

Using JSON

If the object does not have a toString() method defined, and you do not want to (or can not) create a custom one, you can use JSON to verify the contents of an object:

JsonApprovals.verifyAsJson(objectUnderTest);

snippet source | anchor

Will Produce the following File:
GettingStartedTest.testObjectWithJson.approved.json

Containing

{
  "x": 5,
  "y": 10,
  "width": 100,
  "height": 200
}

snippet source | anchor

If you see “ApprovalTests” as the result, simply Approve The Result. Itʼs important to note that you will need to create a useful instance of the toString() Method for objects you want to use.

Arrays

Letʼs say you wanted to test an array of Strings:

@Test
public void testArray()
{
  /* Do */
  // create a String Array and set values in the indexes
  String[] s = new String[2];
  s[0] = "Approval";
  s[1] = "Tests";
  /* Verify */
  // Verify the array
  Approvals.verifyAll("Text", s);
}

snippet source | anchor

Will Produce the following File:

Text[0] = Approval
Text[1] = Tests

snippet source | anchor

Note the use of the label, "Text". This is used to make the generated output easier to read:

Again, simply Approve The Result

Swing / AWT

Letʼs say you wanted to test that youʼve created a JPanel correctly. (This works for anything that extends java.awt.Component : awt, swing, JFrame, Label, etc...)

/* Do */
// create a TV Guide and select a show for 3pm
TvGuide tv = new TvGuide();
tv.selectTime("3pm");
/* Verify */
// Verify the TvGuide
AwtApprovals.verify(tv);

snippet source | anchor

Will Produce the following File:

Expected  Image

First, I want to note that even though there is a UI and a select box for times, Iʼm not “poking” it to select the time. Just because we are looking at the UI at the end, doesnʼt mean I need to manipulate it directly. We are programmers, and are not limited by the constraints of the UI. I simply expose a selectTime(String value) function.

Second, this will produce a .png file containing a screen shot of the JPanel as a result. Simply Approve The Result when itʼs ready.

Third, because these will render differently on different operating systems. These test automatically include a Machine Specific setting NamerFactory.asOsSpecificTest() which adds the os type (e.g: Mac_OS_X) to the file name

Generate Combinations of Parameter Values

To simplify getting more comprehensive sets of test cases, or expanding code coverage, ApprovalTests can generate combinations of possible parameters for a given function.

To do this, create an array of possible values for each parameter passed to a function (up to nine parameters). Call the CombinationApprovals.verifyAllCombinations() method passing the method to be called as a lambda. An example follows:

Integer[] lengths = new Integer[]{4, 5, 10};
String[] words = new String[]{"Bookkeeper", "applesauce"};
CombinationApprovals.verifyAllCombinations((i, s) -> s.substring(0, i), lengths, words);

snippet source | anchor

Will Produce the following File:

[4, Bookkeeper] => Book 
[4, applesauce] => appl 
[5, Bookkeeper] => Bookk 
[5, applesauce] => apple 
[10, Bookkeeper] => Bookkeeper 
[10, applesauce] => applesauce

snippet source | anchor

Note on using primitives: We need to use Integer rather than int so that Java generics will work properly.

Here we are writing a single test that tries all 6 ( 3 ints * 2 String) combinations of inputs and the results those will produce.

This will generate potentially hundreds or thousands of possible combinations of values. As before, the output will be displayed and, if the results are satisfactory, Approve The Result.

Approving The Result

When you run a test using ApprovalTests, it will generate a file named YourTestClass.yourTestMethod.received.txt (or .png, .html, etc.) and place it in the same directory as your test.

For the test to pass, this file must match:

YourTestClass.youTestMethod.approved.txt

There are many ways to do this:

  1. Rename the .received file
  2. Run the "move" command that is displayed (also added to your clipboard) in the command line
  3. Use "use whole file" on a diff reporter

It doesnʼt matter how you do it.

Note: If the files match, then the received file will be deleted.
Note: You must include the .approved. files in your source control.

Reporters

If an approval fails, then a reporter will be called that will report the “.received” and “.approved” files. There are many reporters, and you can create your own.

The simplest way to have your reporter called is to use the Annotation @UseReporter(Reporter.class) You can annotate at either the method or class level.

Here are some common Reporters and uses

Reporter Description
ClipboardReporter Puts the "move" command to accept the "received" file as the "approved" file
DiffReporter Launches an instance of the specified reporter
FileLauncherReporter Opens the .received file in the specified editor
ImageReporter Launches an instance of the specified image diff tool
ImageWebReporter Opens the files in a Web browser
JunitReporter Text only, displays the contents of the files as an AssertEquals failure
NotePadLauncher Opens the .received file in Notepad++ (MS Windows only)
QuietReporter Outputs the "move" command to the console (great for build systems)
TextWebReporter Opens the text files in a Web browser

Supported Diff Tools

See Supported Diff Tools

If your diff tool of choice is not supported, or is in a non-standard install folder, you can always use a Custom Reporter