⚠️ This lesson is retired and might contain outdated information.

Visual Differing Tests with Puppeteer and PixelMatch

Tyler Clark
InstructorTyler Clark
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 2 years ago

Take your end to end tests to the next level by comparing your current application's view with an already accepted screenshot. With the combination of running a live chromium browser, taking a screenshot and running a pixelmatch test, we are able to make sure our UI matches exactly as intended. We will make the test pass and then have it fail by adding an extra p tag to our App.js

Instructor: [00:00] The first thing we need to do is install PixelMatch. With that installed, we can navigate to our pixel test page, and we'll write const puppeteer equals require puppeteer, const devices equals require puppeteer device descriptors, const iphone equals devices iPhone 6, and we're going to do let browser and let page, beforeAll, async.

[00:25] browser equals await puppeteer.launch, with an object with headless as false, page equals await browser.newPage, await page.goTo our local, await page.emulate iPhone, then a afterAll with browser.close.

[00:46] With our require statements and basic Puppeteer setup ready to go, we're now able to start writing our pixel test. We'll write a describe block. Screenshots are correct. Then inside this, we'll do an it index with an async function, const file equals screenshot.png, await page.screenshot, path will be our file. Then return pixelTest.compareScreenshots with that file.

[01:18] Inside of this test, we are going to take and save a screenshot of our current view of localhost 3000. This file path is what we're going to use to pass through to our screenshot, as well as to our pixelTest.compareScreenshots method.

[01:32] This is where we will do the actual comparing of this current screenshot and our already saved screenshot that we'll be testing against. Let's go ahead and require this pixelTest. It'll be coming from diffImages.

[01:45] We'll save this, and navigate to that page. Awesome. In this file, we're going to do const pixelMatch equals require pixelMatch, const fs equals require fs, const png equals require png-js.png. Next, we'll do exports.compareScreenshots equals the file name, arrow function, const image1 equals fs.createReadStream, testScreenshot.png, and then pipe a new png.

[02:22] Then const image2 equals fs.createReadStream, filename.pipe, newPNG.onParse, we're going to do done reading. Awesome. We use a combination of FS and PNG in order to read and parse our two images.

[02:35] As you can see, once the second image is parsed, we want to call a function called doneReading. Inside of this function, we're going to use pixelMatch, and our Jest assertions. Before we do that, we're going to wrap this return in a promise, and move everything inside of it.

[02:54] Now, inside this promise, we'll do const doneReading equals an arrow function. We'll expect image1.width to be image2.width, expect image1.height to be image2.height. Then const numDiffPixels equals pixelMatch, image1.data, image2.data, null, image1.width, image1.height, an object with threshold at 01.

[03:23] Then we'll expect our nonDiffPixels to be zero. Finally, resolve our promise. Perfect. Again, after we've parsed our static test image and our new test instance screenshot, we walk through doneReading. Our first tests are to make sure that the width and height match.

[03:42] This is helpful to catch potential pixel test differences. Next comes the actual pixel testing. Here, we're trying to get the number of pixels that the two images are off by. The first two parameters are the two images that we're testing. In our case, image1 and image2.

[03:59] Next is a differing output image, but since we're not working with one, we're just going to put null, and then the width and height of the images. This last object is for any options we want to specify. This threshold property is the degree of sensitivity that we want the test to work on.

[04:17] This ranges from zero to one. Smaller values makes the comparison more sensitive. Then we expect that the number of differing pixels is zero, and then finish by resolving our promise. Now, before we actually run our test, let's take a look at our test screenshot picture.

[04:38] We can assume that when we run this test, it's going to pass. Both our test screenshot and our active running are the exact same. If we grab our terminal and run our test script, we'll see a browser open, take a screenshot, and compare the two. It passes.

[04:56] We could easily break this test by going to our app JS file, and adding a p tag that says break pixel test. When we save this, we'll see it in our application. Now, we can grab our terminal and rerun our test. This is going to update our screenshot, and compare it. We'll see that we do fail, and this is the amount of pixels that it was off by.

Deniz Oguz
Deniz Oguz
~ 6 years ago

Hi I have started using Cypress.io to write end to end tests. I don't have much experience in Cypress.io but as far as I can view there is no much difference between Puppeteer and Cypress.io. Do you have any guidance on when we should choose Puppeteer and when we should choose Cypress.io. Thanks.

Michael Estwanick
Michael Estwanick
~ 6 years ago

What is the value of this approach instead of using something like jest-image-snapshot?

0 plusX
0 plusX
~ 6 years ago

Great introduction to puppeteer. Thank you very much!

Tyler Clark
Tyler Clarkinstructor
~ 6 years ago

Michael- Jest-image-snapshot uses pixelmatch behind the scenes. From the jest image snapshot docs:

"Jest matcher that performs image comparisons using pixelmatch and behaves just like Jest snapshots do! Very useful for visual regression testing."

Tyler Clark
Tyler Clarkinstructor
~ 6 years ago

Hi I have started using Cypress.io to write end to end tests. I don't have much experience in Cypress.io but as far as I can view there is no much difference between Puppeteer and Cypress.io. Do you have any guidance on when we should choose Puppeteer and when we should choose Cypress.io. Thanks.

Cypress is designed to be a E2E testing tool. So it has a lot more features than puppeteer. Puppeteer is not designed to be used for this purpose and is really just a browser to test with. So it's like comparing apples to oranges. Both have their tradeoffs. There is a course in the works on cypress.io!

Chester Rivas
Chester Rivas
~ 6 years ago

Just go extremely fast and you too can be as a coding God.

Nick
Nick
~ 5 years ago

Doesn't work.

Markdown supported.
Become a member to join the discussionEnroll Today