Testing WordPress Sites with BackstopJS

Introduction

The core idea behind BackstopJS is “show me all the things that changed on the site’s pages.”

It’s intended to check when changing a bit of CSS has unexpected impacts. However, as WordPress integration testers we can use it for much more:

  • Want to check to see if installing a new plugin is going to impact the frontend of your site?
  • Want to verify that one or more plugin updates didn’t have unexpected changes?
  • Does your site depend on external resources, and you need to periodically verify that everything’s still working?

We can use BackstopJSSpecial shout out to Tome Pajkovski for introducing me to this awesome technology! for all of that.

A ‘diff’ of the AdvancedWoo Homepage showing discrepancies between the ref and test screenshots.

Backstop setup

Once again, we have the option to use our docker-compose specialized environmentsIf you prefer to use globally or locally install BackstopJS, that’s fine too—just skip this step.. Map the directoryI’d advise create your directory before spinning up the container, to prevent weird permissions stuff from happening, especially on Linux you want your backstop test data/config in to your docker container in the docker-compose.yml file

backstop:
                image: wpbackstoptests
                network_mode: host
                volumes:
                        - /var/www/html/awd/backstop-tests:/src #edit the left hand side with where you want the backstop archives to live in your filesystem

Once you launch your container, you’ll initialize your environment

backstop init

backstop.json

{
  "id": "backstop_default",
  "viewports": [
    {
      "label": "phone",
      "width": 320,
      "height": 480
    },
    {
      "label": "tablet",
      "width": 1024,
      "height": 768
    },
    {
      "label": "desktop",
      "width": 1280,
      "height": 1024
    },
    {
      "label": "large",
      "width": 1920,
      "height": 1080
    }
  ],
  "onBeforeScript": "puppet/onBefore.js",
  "onReadyScript": "puppet/onReady.js",
  "scenarios": [
    {
      "label": "AdvancedWoo Homepage",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "https://advancedwoo.com/",
      "referenceUrl": "https://advancedwoo.com/",
      "readyEvent": "",
      "readySelector": "",
      "delay": 0,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "expect": 0,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    },
    {
      "label": "AWD How to navigate",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "https://advancedwoo.com/topic/how-to-navigate-this-course/",
      "referenceUrl": "https://advancedwoo.com/topic/how-to-navigate-this-course/",
      "readyEvent": "",
      "readySelector": "",
      "delay": 0,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "expect": 0,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    },
    {
      "label": "AWD data-stores methods",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "https://advancedwoo.com/topic/wc_data-data-stores/#/methods",
      "referenceUrl": "https://advancedwoo.com/topic/wc_data-data-stores/#/methods",
      "readyEvent": "",
      "readySelector": "",
      "delay": 0,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "expect": 0,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    },
    {
      "label": "AWD about",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "https://advancedwoo.com/about/",
      "referenceUrl": "https://advancedwoo.com/about/",
      "readyEvent": "",
      "readySelector": "",
      "delay": 0,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "expect": 0,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    }
  ],
  "paths": {
    "bitmaps_reference": "backstop_data/bitmaps_reference",
    "bitmaps_test": "backstop_data/bitmaps_test",
    "engine_scripts": "backstop_data/engine_scripts",
    "html_report": "backstop_data/html_report",
    "ci_report": "backstop_data/ci_report"
  },
  "report": ["browser"],
  "engine": "puppeteer",
  "engineOptions": {
    "args": ["--no-sandbox"]
  },
  "asyncCaptureLimit": 5,
  "asyncCompareLimit": 50,
  "debug": false,
  "debugWindow": false
}

Within your scaffolded BackstopJS project, you’ll find the backstop.json file. This is where most of the project magic happens.

We won’t go through all the specific configsthe docs are the best place for that, but it’s worth calling out the “Get Started” fields:

  • Viewports:The screen size breakpoints you want to test.
  • Scenarios:The pages you want to test

Backstop Test

To load the latest test screenshots as the reference point, you’ll need to approve the screenshots.

$ backstop approve
$ backstop test

Once you’ve got your config setup, you can run/initialize your tests. However, you should expect a test failure, since there’s no reference yet.

$ backstop test

The Report

Backstop will “fail” if it detects any differences between your reference images and the newly produced test images. Terminal info is not terribly informative.

However, in the backstop_data/html_report/index.html file, we’ll receive a reportif running outside of the docker environment, backstop will actually launch this at the conclusion of any failing report—pretty neat, huh? with an excellent UI to examine the changes.

Special Behaviors

To verify appearance after certain events, look at using the configuration options inside specific scenarios

Often, when testing a WordPress site, it can useful to test certain areas a logged in user. Fortunately–backstop makes this fairly easyCopy a valid wordpress_logged_in cookie value from your browser dev tools (and any other cookies you need), into the array with the backstop_data/engine_scripts/cookies.json file

[
  {
    "domain": "advancedwoo.com",
    "path": "",
    "name": "wordpress_logged_in_926e9e0987654321d0bd64aaa9993b6f381",
    "value": "Chase%7C1612345678%abc123itsaseasyasyouandme%9Ceifyouthinkimtoolazytochangemycookiehashyouarewrong123456789",
    "expirationDate": 2798790400,
    "hostOnly": true,
    "httpOnly": true,
    "secure": true,
    "session": false,
    "sameSite": "no_restriction"
  }
]
"readyEvent": "",
"readySelector": "",
"delay": 0,
"hideSelectors": [],
"removeSelectors": [],
"hoverSelector": "",
"clickSelector": "",
"postInteractionWait": 0,

Conclusion

BackstopJS can truly serve as your backstop against all manner of unexpected frontend changes on your site. Use it’s snapshot comparison tool frequently, update your refs regularly and you’ll have a powerful ally in finding unexpected changes before clients do. 😉

×

Keyboard shortcuts

CTRL+Shift+F Search slideshow
F Fullscreen view
CTRL+Click Zoom in
Esc Topic overview
Right arrow,
Down arrow
Next slide
Left arrow,
Up arrow
Previous slide

Color codes

Tooltip
Hover over text more additional info
Link to an external resource
Link to an internal slide
If buttons aren't working, click in the screen to "focus" your browser
RSS
LinkedIn
Share