Automated browser snapshot testing made easy: Run your tests in 10 minutes

Snapshot testing is a commonly used method that consists of taking application screenshots and comparing them with previous ones. Every time the application is modified, both old and new captures must match to a certain degree for the test to be considered as passed. It is a great way to make sure the changes we perform in our daily development won't break the structural appearance of the application or website we are building, but normally requires tedious configurations and complex code structures to be executed. So it is important to have an easy way to integrate these kinds of tests into our workflow and improve our testing productivity.

Turboframework (via the Turbotesting library) provides us with an easy way to write these kinds of tests. With a few lines of code, we can instruct the testing framework to take a snapshot and compare it with a previous one. In case there is no previous snapshot stored yet, the test will pass and the current snapshot will be stored for use with future test executions. Many extra handy features are available like specifying ignore regions in case we need to be more flexible with the differences between both snapshots, always using standard technologies like:

Writing automated snapshot tests for a website or web app is extremely easy with turboframework. Let's see how

Set up your environment and create a tests project

Make sure you have installed the turbobuilder CMD tool: it will be used to run the tests. If you want to read a detailed guide on how to set it up and create a project to run your tests follow this link. The whole process is done in 10 minutes.

Write and execute your first snapshot test

With turbobuilder CMD installed and a project created, let's write a test that opens a browser window, scales the viewport to 800x600, takes a snapshot, and compares it with the previously stored one. To do it, create a new javascript file inside our tests project: my_test_project\src\test\js\spec\my-first-snapshot-test.js and then copy the following code inside it:

'use strict';

const { AutomatedBrowserManager } = require('turbotesting-node');
const { FilesManager } = require('turbodepot-node');

const fm = new FilesManager();

describe('my-first-snapshot-test', function() {

    // This is executed before any test is executed
    beforeAll(async function() {
        this.automatedBrowserManager = new AutomatedBrowserManager();
        this.automatedBrowserManager.initializeChrome();
    });

    // This is executed after all tests are executed
    afterAll(async function() {
        await this.automatedBrowserManager.quit();
    });

    // Here we are performing the viewport resize, url loading and snapshot comparison
    // Notice that fm.getOSTempDirectory() indicates the test to store the site snapshot to the OS temporary directory
    // when there is a mismatch with the expected one. This way we can easily replace it in our test if we think that differences
    // are valid
    it('should match the previously stored google site snapshot', async function() {
        await this.automatedBrowserManager.queryCalls([
            ['loadUrl', "https://google.com"],
            ['setBrowserSizeAndPosition', 800, 600, 0, 0],        
            ['assertSnapshot', './src/test/google-snapshot.png', fm.getOSTempDirectory(), {}]
        ]);
    });
});

To run this test we will execute the following cmd commands at the root of our project folder:

npm install
tb -t

This first time the test will be always a PASS, cause there is no snapshot yet, so it will be generated and stored to ./src/test/. We will need to run the test again to perform the snapshot comparison:

tb -t

A web browser should open automatically, load the google.com URL, resize the window viewport to 800x600 and verify that the viewport snapshot matches the previous one. After that, our cmd should display 'test ok'

Ignore specific viewport regions

Snapshot tests are usually difficult to maintain because any minimal change into the application may result in a test failure when comparing the new snapshot with the previous one. For example, changing a text will make the test fail but the application may still be correct. To avoid such cases, we can specify one or more rectangular areas that will be ignored inside the snapshot. This will make the test more change-resistant and still powerful enough to test most of the visual appearance of our application or website. Let's see a test example:

    it('should match a snapshot but ignore several regions', async function() {
        await this.automatedBrowserManager.queryCalls([
            ['loadUrl', "https://google.com"],
            ['setBrowserSizeAndPosition', 800, 600, 0, 0],
            ['assertSnapshot', './src/test/google-snapshot-2.png', fm.getOSTempDirectory(),
                {ignoreRegions: [
                    {x:0, y:0, width:50, height:50},
                    {x:100, y:100, width:100, height:100}]}],
        ]);
    });

This test will resize the browser so its viewport is 800x600, perform a viewport snapshot and compare it with the stored one (the first time will be generated and stored to the provided path). Just like the previous example, but in this case, two rectangular regions of the snapshot are being specified to be ignored: A 50x50 pixels rectangle located at x=0 and y=0, and a 100x50 pixels rectangle located at x=100 and y=100. This way, our test will be tolerant to any change inside that area.

What's next

In this post, we have configured and launched a basic snapshot comparison test. It's a starting point that gives us the tools we need to perform any of these kinds of tests easily and fast. Keep an eye on our blog for more interesting testing and software tutorials!