Introduction to PhantomCSS

Created by Jonathan Petitcolas / @Sethpolma

Server side

PHPUnit
PHPUnit, JUnit and all other XUnit stuff

Javascript

Selenium
Selenium, Mocha, and some others

CSS

Only manual testing...

SuperGhost
But, that was before!

This is NOT PhantomCSS logo, just DeviantART! :(

PhantomCSS

A CasperJS module for automating visual regression testing with PhantomJS and Resemble.js. For testing Web apps, live style guides and responsive layouts.

https://github.com/Huddle/PhantomCSS

CasperJS

CasperJS is a navigation scripting & testing utility for PhantomJS and SlimerJS written in Javascript

http://casperjs.org/

SlimerJS

SlimerJS allows you to interact with a web page through an external JS script.

http://slimerjs.org/

PhantomJS

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

http://phantomjs.org/

Resemble.js

Resemble.js analyses and compares images with HTML5 canvas and JavaScript.

http://huddle.github.io/Resemble.js/

Installing PhantomCSS

# Installing PhantomJS
sudo npm install -g phantomjs

# Retrieving PhantomCSS sources
git clone [email protected]:Huddle/PhantomCSS.git

# Launching default test suite
phantomjs demo/testsuite.js

Pratical case: back to the past!

Back to the future
Coming soon page

With some awesome animated GIF!

Hammer
<TABLE width=100% height=100%>
    <TR>
      <TD width=100% height=100% align=center valign=center>
        <TABLE>
          <TR align=center>
            <TD align=center><IMG src=img/hammer.gif></IMG></TD>
          </TR>
          <TR align=center valign=center>
            <TD><FONT size=7 color=red>Coming soon</FONT></p></TD>
          </TR>
          <TR>
            <TD align=center><FONT size=5>Our website is currently under construction.</FONT></TD>
          </TR>
          <TR>
            <TD align=center><BR><BR>
              <FONT size=4>
                <script type=text/javascript>
                  var date = (new Date()).toString()
                  document.write(date.split(' ').splice(1,4).join(' '));
                </script>
              </FONT>
            </TD>
          </TR>
        </TABLE>
      </TD>
    </TR>
    <TR cellpadding=50>
      <TD align=center>
        <BR><BR><BR>
        <FONT size=2 color=#666>
          Website proudly created by <A href=#>FrontWeaver MX Gurus</A>
          - © 1991 All rights reserved
        </FONT>
      </TD>
    </TR>
  </TABLE>

Bootstrapping PhantomCSS

phantom.casperPath = './CasperJs';
phantom.injectJs(phantom.casperPath + '/bin/bootstrap.js');

var casper = require('casper').create({
    viewportSize: {
        width: 800,
        height: 600
    }
});

var phantomcss = require('./phantomcss.js');
var url = 'http://phantomcss/index.html';

phantomcss.init({
    screenshotRoot: './screenshots',
    failedComparisonsRoot: './failures'
});

Writing our first PhantomCSS test

casper
    .start(url)
    .then(function() {
        phantomcss.screenshot('.coming_soon', 'coming-soon-page');
    })
    .then(function() {
        phantomcss.compareAll();
    })
    .run(function() {
        phantom.exit(phantomcss.getExitStatus());
    });

First launch

jpetitcolas@jp-dev ~/dev/phantomcss $ phantomjs tests/css/coming-soon.js

Must be your first time?
Some screenshots have been generated in the directory ./screenshots
This is your 'baseline', check the images manually. If they're wrong, delete the images.
The next time you run these tests, new screenshots will be taken.
These screenshots will be compared to the original.
If they are different, PhantomCSS will report a failure.
Base screenshot for coming soon page
We have to go back!

Refactoring code

<div class="coming_soon">
  <img src="img/hammer.gif" alt="Under construction..." title="Under construction..." />
  <h3>Coming soon</h3>
  <p>Our website is currently under construction.</p>
  <p class="date" id="date"></p>
</div>
<footer>
  <p
    >Website proudly created by <a href="#">FrontWeaver MX Gurus</a>
    - © 1991 All rights reserved
  </p>
</footer>
<script>
  var date = new Date().toString().split(' ').splice(1,4).join(' ');
  document.getElementById("date").innerText = date;
</script>

Be pragmatic!

jpetitcolas@jp-dev ~/dev/phantomcss $ phantomjs tests/css/coming-soon.js
Failing screenshot after refactoring

Avoid dynamic data

Failing screenshot because of date

Mocking Javascript is easy!

casper
    .start(url)
    .then(function() {
        var Date = function () {
            return {
                toString: function() {
                    return 'Sun Sep 15 2013 10:28:50 GMT+0200 (Romance Daylight Time)';
                }
            }
        }

        phantomcss.screenshot('.coming_soon', 'coming-soon-page');
    })

Best practices

  • Name your screenshots
  • KISS CSS
  • Test only what you need to
  • Forget fullpage screenshots
  • Commit only base pictures
  • Use same browsers/OS

Any questions?

Questions?

THE END

www.jonathan-petitcolas.com

https://github.com/jpetitcolas/talk-phantomcss