5. Why test?
• We all want to write code that works.
• Testing improves reliability.
• Repeatedly testing minimises regressions.
• Automatic testing can pick up “dumb-ass”
mistakes.
6. That sounds lovely
• Normally that doesn’t happen though.
• Normally what happens is...
7. 1. We build things.
They adhere to our
standards.
15. So...
• Test automatically and often.
• By adhering to a known standard, and
constantly testing against it, it becomes
easier to spot problems with the code that
we're writing.
16. And that saves money
Fewer bugs
==
Less time fixing bugs
==
More time developing new features.
18. What’s normally tested
Backend Frontend In-Browser
(API, functions) (HTML, CSS, JS) (Functional)
Validators, JsLint,
*Unit Selenium
YSlow etc.
Sometimes
Automatic via CI Manual
automatic via CI
Adhoc, when
Well defined Fairly well defined
remembered
19. Why not use Selenium?
• Selenium tests code after it’s been
interpreted by the browser.
• Good for functional testing, not so good for
testing discrete units of code.
20. Discrete Units?
• I’m looking at testing the quality of our
HTML, CSS and JavaScript.
• It should all adhere to a known standard.
21. So we’re testing what?
• The code that leaves the server.
• Before it is interpreted by the browser.
22. What should we test?
• Currently I’m testing against:
• W3C HTML Validator validator.w3.org
• W3C CSS Validator jigsaw.w3.org/css-validator
• JsLint jslint.com
23. Validation is a dirty word
• People don’t like the word.
• They always ask “what if?”.
27. How do I do this testing?
• I’ve been writing a test suite!
• http://github.com/NeilCrosby/frontend-
test-suite (CC Attribution-Share Alike)
28. Currently in Phase 1
• Tests can easily be run against known units
of HTML, CSS and JavaScript.
• I’m using phpunit as the framework.
29. HTML Testing
• By default tests against HTML 4.01 Strict.
• Test against custom DTDs.
• Module and full page testing.
• Test files, URLs or strings.
30. CSS Testing
• By default tests against CSS 2.1.
• Known exceptions to the standards can be
allowed to pass validation.
• Test files, URLs or strings.
32. Add to your CI
• Run these tests in your hourly builds.
• Run them as a pre-commit hook.
33. Be a good citizen
• You’ll be running these tests frequently.
• Set up your own local versions of the
HTML Validator, CSS Validator and JsLint.
• Instructions available on the web.
34. Running these tests
• If you need to test a simple site, it’s easy -
pass a config object to
TheCodeTrainEasyFrontendTestSuite.
• Otherwise, write custom TestCase
extensions (still not hard).
44. The Options Array
‘options’ => array(
‘doctype_override’ =>
‘<!DOCTYPE HTML SYSTEM
quot;http://site/doctype.dtdquot;>’,
‘document_section’ =>
TheCodeTrainHtmlValidator::HTML_CHUNK,
‘document_section_position’ =>
TheCodeTrainHtmlValidator::POSITION_HEAD
)
45. The Options Array
‘options’ => array(
‘doctype_override’ =>
‘<!DOCTYPE HTML SYSTEM
quot;http://site/doctype.dtdquot;>’,
‘document_section’ =>
TheCodeTrainHtmlValidator::HTML_CHUNK,
‘document_section_position’ =>
TheCodeTrainHtmlValidator::POSITION_HEAD
)
46. The Options Array
‘options’ => array(
‘doctype_override’ =>
‘<!DOCTYPE HTML SYSTEM
quot;http://site/doctype.dtdquot;>’,
‘document_section’ =>
TheCodeTrainHtmlValidator::HTML_CHUNK,
‘document_section_position’ =>
TheCodeTrainHtmlValidator::POSITION_HEAD
)
47. The Options Array
‘options’ => array(
‘doctype_override’ =>
‘<!DOCTYPE HTML SYSTEM
quot;http://site/doctype.dtdquot;>’,
‘document_section’ =>
TheCodeTrainHtmlValidator::HTML_CHUNK,
‘document_section_position’ =>
TheCodeTrainHtmlValidator::POSITION_HEAD
)
48. Options?
• Custom doctypes, full page or module,
position on page.
• Options can also be given for individual
tests.
array(
‘file://some/file/to/test’,
array( your_options )
)
49. Running these tests
> phpunit SomeTestSuite
PHPUnit 3.3.1 by Sebastian Bergmann.
.........
Time: 7 seconds
OK (9 tests, 9 assertions)
50. Some failures
....F.....
Failed asserting that
Array
(
[0] => Array
(
[line] => 7
[errortype] =>
[error] => syntax of attribute value does not conform to declared value
[original_line] => <label for=quot;quot;>Some label</label>
)
)
is false.
51. Some failures
.....F....
Failed asserting that
Array
(
[0] => Array
(
[line] => 1
[errortype] => parse-error
[error] => Value Error : display (http://www.w3.org/TR/CSS21/
visuren.html#propdef-display) inlin is not a display value :
[original_line] => p
)
)
is false.
56. Phase 2 - The Future
• Test for things a simple DTD check can’t
pick up on.
• CodeSniffer.
• Whitelisting sections of code - e.g. adverts.
• Basic accessibility testing - working with the
experts at Yahoo!.
57. Available Online
• This talk: http://icanhaz.com/aft
• The Code (please fork and contribute):
http://github.com/NeilCrosby/frontend-
test-suite
• Twitter: automated frontend testing,
@NeilCrosby
• My blog hub: http://neilcrosby.com
Editor's Notes
I’m also lazy.
Unfiltered data
labels pointing to non-existent input elements