Developing on Staxmanade

Approval Tests - Overview

(Comments)

I first started using the .Net version of Approval Tests and found so much value in it, I created a port of the tool that I can use in Node.JS. This post is intended as a rough overview of Approval Tests, and will be using the NodeJS port in my examples below.

There is support for other programming languages, so head over to the Approval Tests site at ApprovalTests.com and check them out.

What are Approval Tests?

At it's core, Approval Tests are a very different way to execute the assertion step of a unit test.

Think of this as another tool in the bag and not a replacement for the good old fashion assert.equal(...) or your favorite assertion tool. But for certain types of tests, it IS the best tool to grab.

Typically, when we create assertions in our unit tests, we assert on very specific things. This property equals that value.

With Approval Tests, you can take whatever output you're wanting to Assert against, turn it into either a string representation or an image (say screenshot of app), and use our favorite diff tool to compare it with the previously approved version.

The diff tool is a great way to visualize change between failing/approved data which can help to raise the level of abstraction of your test. Instead of comparing a single value in an assertion, we can serialize an entire object graph to a string and use the diff tool to review any changes to the diff of the previously approved version.

The work to find and start up your favorite diff tool comparing previously "approved" files is where the libraries provided by Approval Tests come in handy.

Let's walk through an example

If you've done any testing before, by now you have probably heard of the AAA (Arrange, Act, Assert) style of tests. Below I've contrive a sample test using the AAA style in JavaScript.

var assert = require('assert');
describe("when testing something", function(){
    it("should do something special", function(){

        // Arrange
        // setup the initial state for the test
        var obj = { valueA: "test", valueB: 1234 };

        // Act - Do some business logic on the object
        obj.valueC = true;

        // Assert - verify the state of the item under test
        assert.equal(obj.valueA, "test")
        assert.equal(obj.valueB, 1234);
        assert.equal(obj.valueC, true);
    });
});

At a high level, if you are writing tests with an object, and have a way to translate that object's state into a text or image representation, wouldn't it be great if you could save that state into a file, essentially locking down the state of the test?

This would allow future runs of the test to easily detect a change by comparing the previous state with the new state (strings of course) - but using the power of our diff tools to quickly highlight what is different.

Let's turn our AAA test above into an Approval Test

var approvals = require('approvals');
describe("when testing something", function(){
    it("should do something special", function(){

        // Arrange
        // setup the initial state for the test
        var obj = { valueA: "test", valueB: 1234 };

        // Act - Do some business logic on the object
        obj.valueC = true;

        // Assert - verify the state of the item under test
-        assert.equal(obj.valueA, "test")
-        assert.equal(obj.valueB, 1234);
-        assert.equal(obj.valueC, true);
+        approvals.verifyAsJSON(__dirname, "sampleTest", obj);
    });
});

Notice how the 3 assert's turned into 1 approvals.verifyAsJSON?

How Approval Tests Work

Approval Tests works by taking the object or value you're trying to verify, serializing it to a text file (or image) and saving it to a file labeled with the name of your test and *.received.txt. It will then try to compare this *.received.txt file with a *.approved.txt file. If the file doesn't exist, then we will see a diff tool present with our received file on the left and an empty approved file on the right.

At this point we have to choose between a number of options:

  • We could take the received output and copy/save it to the approved file. Essentially approving the test.
  • We may only want parts of the received file, and copy over just the parts of what we want to the approved file.
  • Or we do nothing as we want to start over...

Now we run our test again and if the test passes - then we know that we've finished as what was re-generated in the received file matches the approved file. But if we see our diff tool appear, we can analyze the differences in the diff tool and determine if we need to either adjust the approved file or adjust our code that generates the received file.

If the above explanation still isn't clear, I'd recommend watching @LlewellynFalco's video's on the topic that can be found at approvaltests.com. He does a good job describing the concepts.

Next Steps!

Browse the github org, watch videos or read documentation on approvaltests.com.

Happy Approving!

Comments