forked from rupl/frontend-testing
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
477 lines (436 loc) · 22.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Automated Frontend Testing</title>
<meta name="description" content="Automated Frontend Testing — a slides describing how to perform functional testing with CasperJS and performance monitoring with grunt-phantomas and WebPageTest.org">
<meta name="author" content="Chris Ruppel">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link href='http://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/print.css" type="text/css" media="print">
<link rel="stylesheet" href="lib/github.css">
<link rel="stylesheet" href="lib/prism.css">
</head>
<body>
<div class="reveal">
<!-- Used to fade in a background when a specific slide state is reached -->
<div class="state-background"></div>
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section data-state="bluesy">
<br><br>
<h1 style="font-size: 3.2em; ">Automated Frontend Testing</h1><br>
<p class="fragment insert-container">Or: How to Automate the Process of <span class="insert fragment">detecting when you</span> Break Things</p>
<script>
// Delicously hacky. Look away.
if( navigator.userAgent.match( /(iPhone|iPad|iPod|Android)/i ) ) document.write( '<p style="color: rgba(0,0,0,0.3); text-shadow: none;">('+'Tap to navigate'+')</p>' );
</script>
</section>
<section>
<h2>Chris Ruppel</h2>
<section>
<br><br>
<p>frontend dev @ <a href="http://fourkitchens.com">Four Kitchens</a></p>
<p><a href="http://twitter.com/rupl">twitter.com/rupl</a></p>
<p><a href="https://github.com/rupl">github.com/rupl</a></p>
</section>
<section>
<a href="http://fourkitchens.com"><img src="img/4k-logo-square-500px.png" alt="Four Kitchens" style="border: 0; box-shadow: none; "></a><br>
<small><a href="http://fourkitchens.com/careers">(we're hiring!)</a></small>
</section>
<section>
<br><br>
<p style="font-size: 1.25em;">I contribute and present about open source:</p><br>
<ul class="fragment">
<li><a href="http://rupl.github.io/unfold/">Unfolding the Box Model</a>
<li><a href="https://www.drupal.org/project/modernizr">Modernizr Drupal module</a>
<li><a href="https://www.drupal.org/project/web_components">Web Components API</a></li>
<li><a href="https://www.drupal.org/project/fastclick">FastClick Drupal module</a>
<li><a href="https://www.drupal.org/sandbox/joel/2121797">Prerender/Prefetch Drupal module</a>
</ul>
</section>
</section>
<section>
<h2>Why do I need frontend testing?</h2>
<section>
<br>
<p>There are untold number of subtle<br> errors that can occur on the frontend.</p>
<br>
<ul>
<li class="fragment">Minor CSS changes that throw things off</li>
<li class="fragment">Changes to JS files that break things</li>
<li class="fragment">Aggregates changing when not necessary</li>
<li class="fragment">Performance regressions<br><br></li>
</ul>
</section>
<section>
<br>
<p>Additionally, frontend development is<br> becoming more critical as the trade matures.</p>
<br>
<p class="fragment">We need the same testing abilities<br> that the backend has had for years.</p>
</section>
<section>
<br>
<ul>
<li class="fragment">Testing page load times</li>
<li class="fragment">Testing render speeds</li>
<li class="fragment">Sticking to a performance budget</li>
<li class="fragment">Verifying visual changes</li>
<li class="fragment">Accountability for code changes</li>
</ul>
</section>
</section>
<section data-state="soothe">
<section>
<h2>workflow_alter()</h2>
<br>
<p>In order to deliver the best, fastest site possible, we have to change our development processes.</p>
<br>
<blockquote class="fragment" cite="http://www.igvita.com/slides/2013/io-pagespeed.pdf"><q>Performance is not a checklist, it's a<br> <strong>continuous</strong> process.</q> — <a href="http://www.igvita.com/slides/2013/io-pagespeed.pdf">Ilya Grigorik</a></blockquote>
<br>
<blockquote class="fragment" cite="http://www.netmagazine.com/features/speeding-mobile-html5-experiences"><q>…don’t take measures without measuring them.</q><br> — <a href="http://www.netmagazine.com/features/speeding-mobile-html5-experiences">Maximiliano Firtman</a></blockquote>
</section>
</section>
<section>
<h1>YES</h1>
<br>
<p class="fragment">The slides AND code are on GitHub, I will tweet the link, and it's already available on the session page of the DrupalCon site. Yes, you may <a href="https://github.com/rupl/frontend-testing/blob/gh-pages/LICENSE.md">take code from the slides</a> and use it for any purpose :)</p>
<br>
<p class="fragment">This presentation is using a fresh clone of these slides, using the many <a href="https://github.com/rupl/frontend-testing/tree/gh-pages/examples">examples I provided in the repo</a>.</p>
</section>
<section>
<section data-state="blackout">
<br>
<h1>Functional testing</h1>
</section>
<section>
<h2>CasperJS</h2>
<p>Casper allows for scripted actions to be tested. It uses all the power that PhantomJS offers.</p>
<br>
<ul>
<li class="fragment">Run the same test with multiple screen sizes.</li>
<li class="fragment">Test complex features or components.</li>
<li class="fragment">Automate complex user actions.</li>
<li class="fragment">Test content creation, transactions, other features.</li>
<li class="fragment">Keep an eye on problematic pages.</li>
</ul>
</section>
<section>
<h2>Test frontend components</h2>
<br>
<pre><code class="language-bash"># test the canonical picturefill demo
$ casperjs test picturefill.js</code></pre>
<br>
<p class="fragment"><a href="http://fourword.fourkitchens.com/article/using-casperjs-test-picturefill">Read the blog post</a> or <a href="https://www.youtube.com/watch?v=3qNdxjfgbAg">watch a screencast</a><br> describing this test in detail.</p>
</section>
<section>
<h2>Simulate user actions</h2>
<br>
<pre><code class="language-bash"># test simple user actions like clicking,
# keyboard navigation, filling forms
$ casperjs test user-actions.js</code></pre>
<br>
<p class="fragment"><a href="http://fourword.fourkitchens.com/article/simulate-user-actions-casperjs">Read the blog post</a> describing this test in detail.</p>
</section>
<section>
<h2>Test author<br> workflow in Drupal</h2>
<br>
<pre><code class="language-bash"># test a Drupal demo site, log in, add content
$ casperjs test drupal.js</code></pre>
<br>
<p class="fragment"><a href="http://fourword.fourkitchens.com/article/testing-drupal-casperjs">Read the blog post</a> or <a href="http://www.youtube.com/watch?v=qhA6O1u97PE#t=1283">watch a video</a>.</p>
</section>
<section>
<br>
<h2>More examples</h2>
<br>
<p>Keep checking our blog post series on the Four Kitchens blog to <a href="http://fourword.fourkitchens.com/article/series/casperjs">learn more about CasperJS</a>.</p>
</section>
</section>
<section>
<section data-state="blackout">
<br>
<h1>Performance Testing</h1>
</section>
<section>
<h2>Automating PageSpeed</h2>
<br>
<p class="fragment">Google has a service called <a href="https://developers.google.com/speed/pagespeed/insights/">PageSpeed Insights</a> that grades your site and boils down tons of factors into a "speed index"</p>
<br>
<p class="fragment">
Testing sites can be automated. <a href="https://developers.google.com/speed/docs/insights/v1/getting_started#auth">Get your API key first</a>.
<br><br>
</p>
<p class="fragment"><small>Or you can sign up for the <a href="https://developers.google.com/speed/pagespeed/service">PageSpeed service</a>.</small></p>
</section>
<section>
<h2>grunt-pagespeed</h2>
<br>
<p><a href="https://developers.google.com/speed/docs/insights/v1/getting_started">PageSpeed API</a> is documented quite<br> thoroughly, but there's also a <a href="https://github.com/jrcryer/grunt-pagespeed">grunt plugin</a>.</p>
<br>
<pre><code class="language-bash"># examples/grunt/pagespeed
$ npm install
$ grunt # runs default task
$ grunt pagespeed:mobile # runs mobile task</code></pre>
<br>
<small><a href="https://github.com/rupl/frontend-testing/tree/gh-pages/examples/grunt/pagespeed/Gruntfile.js">View code on GitHub</a></small>
</section>
<section>
<h2>Phantomas</h2>
<br>
<p class="fragment"><a href="https://github.com/macbre/phantomas">Phantomas</a> is a PhantomJS-based<br> web performance metrics tool</p>
<br>
<p class="fragment">It gives you loads of data about how the<br> frontend of your website is performing.</p>
<br>
<p class="fragment">The <a href="https://github.com/macbre/phantomas#usage">usage guide</a> is extensive.</p>
</section>
<section>
<br>
<pre><code class="language-bash"># run a basic report
$ phantomas --url http://gruntjs.com
# set viewport dimensions, generate images of rendering process
$ phantomas --url http://gruntjs.com --viewport=320x480 --film-strip
# assert a test for total number of requests
$ phantomas --url http://gruntjs.com --assert-requests=20
</code></pre>
</section>
<section>
<h2>grunt-phantomas</h2>
<br>
<p class="fragment">This grunt plugin is not just a wrapper for running the tool.</p>
<br>
<p class="fragment">It provides detailed reports that track your data over time, allowing you to identify trends using dynamic charts that update themselves each time you run the grunt task</p>
<br>
</section>
<section>
<img src="img/grunt-phantomas-graph.png" alt="Graph displaying a spike in CSS size." style="position: relative; top: -2em;">
</section>
<section>
<br>
<pre><code class="language-bash"># examples/grunt/phantomas
$ grunt phantomas:default
# run report and generate screenshot
$ grunt phantomas:screenshot
# test for certain values. this might cause failure!
$ grunt phantomas:requests</code></pre>
<br>
<small><a href="https://github.com/rupl/frontend-testing/tree/gh-pages/examples/grunt/phantomas/Gruntfile.js">View code on GitHub</a></small>
</section>
<section>
<h2>Performance Budgets</h2>
<br>
<p class="fragment">The idea is simple: <a href="http://timkadlec.com/2013/01/setting-a-performance-budget/">performance budgets</a> are just like a monthy expense budget. We should keep track of how fat our sites grow over time.</p>
<br>
<p class="fragment">grunt-phantomas has <a href="https://github.com/stefanjudis/grunt-phantomas/issues/86">performance budget features</a> that visualize over-budget metrics that you set.</p>
</section>
<section>
<h2>grunt-perfbudget</h2>
<br>
<p class="fragment">Tim Kadlec, who first suggested performance budgets, recently released this tool to help teams meet their goals.</p>
<br>
<p class="fragment">grunt-perfbudget relies on the immensely useful <a href="http://webpagetest.org">WebPageTest</a> API to enforce a budget.</p>
<br>
<p class="fragment">WebPageTest.org and its API are much more flexible than PhantomJS tools, because it can leverage multiple browsers, geographic locations, and network speeds.</p>
</section>
<section>
<pre><code class="language-bash"># examples/grunt/perfbudget
$ npm install
# run report
$ grunt perfbudget
</code></pre>
<small><a href="https://github.com/rupl/frontend-testing/tree/gh-pages/examples/grunt/perfbudget/Gruntfile.js">View code on GitHub</a></small>
</section>
<section>
<img src="img/grunt-perfbudget-output.png" alt="Output of grunt-perfbudget task" width="960" style="position: relative; top: -1em; ">
<p><small><a href="http://www.webpagetest.org/result/140529_CK_5V7/">View this result on webpagetest.org</a></small></p>
</section>
</section>
<section>
<section data-state="blackout">
<br>
<h1>CSS Regression testing</h1>
</section>
<section>
<br>
<p>CSS regressions? say it ain't so!</p>
<br>
<p class="fragment">Having no scope at all, CSS is<br> the easiest thing to nudge out of place.</p>
<br>
<p class="fragment">It's also easier to prevent than you think.</p>
</section>
<section>
<h2>Wraith</h2>
<p class="fragment">Wraith uses either Phantom or Slimer (your choice) to take screenshots of two environments, producing a visual diff of the two screenshots.</p>
<img class="fragment" src="img/wraith-example.png">
</section>
<section>
<h3>Basic usage of Wraith</h3>
<br>
<pre><code class="language-bash"># examples/wraith
$ gem install wraith
# run the capture process
$ wraith capture demo
# view results in the browser
$ open shots/gallery.html</code></pre>
</section>
<section>
<h3>Multiple tests</h3>
<br>
<p>Wraith handles one comparison per config file.</p>
<br>
<p class="fragment">However, it has support for multiple configs, so several config files in one repo allows for multiple comparisons.</p>
<br>
<p class="fragment"><a href="https://github.com/BBC-News/wraith#wraith">Read more on GitHub</a></p>
</section>
</section>
<!-- <section>
<section>
<h2>QA and Testing</h2>
<br><br>
<p class="fragment">Testing in loads of browsers is a<br> necessary but tedious task.</p>
<br><br>
<p class="fragment">Services like <a href="http://browserstack.com">BrowserStack.com</a><br> make testing much simpler.</p>
</section>
<section data-state="big-img">
<img class="bare" style="margin-top: -200px; " src="img/browserstack-screenshots.png" alt="visit browserstack.com/screenshots to automatically test in over 300 browsers.">
</section>
</section> -->
<section data-state="blackout">
<section>
<br><h1>Automating Tasks with CI</h1>
</section>
<section>
<h2>The Basics</h2>
<br>
<p class="fragment">Everything outlined in this section<br> requires two key ingredients:</p>
<br>
<ul class="fragment">
<li>Continuous integration (CI)</li>
<li><a href="http://git-scm.com/book/ch7-3.html">Git hooks</a></li>
</ul>
<br><br>
<p class="fragment">Four Kitchens uses <a href="http://jenkins-ci.org/">Jenkins</a> and <a href="https://help.github.com/articles/post-receive-hooks">GitHub WebHooks</a><br> in our workflow, and you can use whatever you wish.</p>
</section>
</section>
<section>
<section>
<h2>Trigger Jenkins builds<br> by pushing to GitHub</h2>
<br>
<p class="fragment">An oldie but goodie: <a href="http://fourkitchens.com/blog/2011/09/20/trigger-jenkins-builds-pushing-github">check out our how-to from 2011</a></p>
<br>
<ol class="fragment">
<li>You push to GitHub master branch (or merge PR)</li>
<li>GitHub pings your CI server using post-receive hook</li>
<li><em>"Yo Jenkins, the repository was updated!"</em></li>
<li>CI server pulls the new code to your staging area</li>
</ol>
<br>
<br>
<p class="fragment">Although fairly mundane in terms of CI, the blog post illustrates the basic concepts underlying all of the tasks involving Jenkins.</p>
</section>
<section>
<h2>Use git hooks to test before pushing code</h2>
<br>
<p class="fragment">Git can be configured to automatically run<br> tasks before or after many of its operations.</p>
<br>
<p class="fragment">pre-commit hook that runs jshint on your JavaScript.</p>
<br>
<p class="fragment">pre-push hook that runs Phantomas assertions on your environment. Helps enforce performance budgets.</p>
</section>
</section>
<section>
<section data-state="blackout">
<br><br><h1>Automated Testing Services</h1>
</section>
<section>
<br><h2>Ghost Inspector</h2><br>
<p class="fragment">If you have a team willing to code up these examples, great! I like writing tests to complement code.</p><br>
<p class="fragment">If not, Ghost Inspector can record a user's actions as they browse normally, and turn those actions into Casper code.</p><br>
<p class="fragment"><a href="https://ghostinspector.com/">Ghost Inspector</a></p>
</section>
</section>
<section>
<br>
<h2>Further reading</h2>
<br>
<ul>
<li><a href="http://www.smashingmagazine.com/2013/06/11/front-end-ops/">Frontend Ops</a> by Alex Sexton</li>
<li><a href="https://speakerdeck.com/addyosmani/automating-front-end-workflow">Automating Frontend Workflow</a> by Addy Osmani</li>
<li><a href="http://yeoman.io/blog/performance-optimization.html">Grunt/Gulp tasks for Performance Optimization</a></li>
<li><a href="https://drupalize.me/blog/201410/using-remote-debugger-casperjs-and-phantomjs">Remote debugging for Casper/Phantom</a> by Joe Shindelar</li>
</ul>
</section>
<section data-state="blackout">
<h1>Questions?</h1>
<br>
<p>Contact me:</p>
<p><a href="https://www.drupal.org/u/rupl">drupal.org/u/rupl</a></p>
<p><a href="https://github.com/rupl">github.com/rupl</a></p>
<p><a href="https://twitter.com/rupl">twitter.com/rupl</a></p>
<p>chris ❀ fourkitchens.com</p>
</section>
<section data-state="bluesy">
<h2>Rate this session!</h2>
<br>
<p>
<a href="https://austin2014.drupal.org/session/automated-frontend-testing">Visit the session page</a> to leave feedback.
<br>
<small>It means a lot to me ❤ Thanks!</small><br><br>
Short link: <a href="http://j.mp/ams-testing">j.mp/ams-testing</a><br><br>
Select <i>"Provide feedback on this session"</i>
</p>
</section>
</div>
<!-- The navigational controls UI -->
<aside class="controls">
<a class="left" href="#">◄</a>
<a class="right" href="#">►</a>
<a class="up" href="#">▲</a>
<a class="down" href="#">▼</a>
</aside>
<!-- Displays presentation progress, max value changes via JS to reflect # of slides -->
<div class="progress"><span></span></div>
</div>
<!-- Optional libraries for code syntax highlighting and classList support in IE9 -->
<script src="lib/classList.js"></script>
<script src="lib/prism.js"></script>
<script src="js/reveal.js"></script>
<script>
// Parse the query string into a key/value object
var query = {};
location.search.replace( /[A-Z0-9]+?=(\w*)/gi, function(a) {
query[ a.split( '=' ).shift() ] = a.split( '=' ).pop();
} );
// Fires when a slide with data-state=customevent is activated
Reveal.addEventListener( 'customevent', function() {
alert( '"customevent" has fired' );
} );
// Fires each time a new slide is activated
Reveal.addEventListener( 'slidechanged', function( event ) {
// event.previousSlide, event.currentSlide, event.indexh, event.indexv
} );
Reveal.initialize({
// Display controls in the bottom right corner
controls: true,
// Display a presentation progress bar
progress: true,
// If true; each slide will be pushed to the browser history
history: true,
// Loops the presentation, defaults to false
loop: false,
// Flags if mouse wheel navigation should be enabled
mouseWheel: true,
// Apply a 3D roll to links on hover
rollingLinks: true,
// UI style
theme: query.theme || 'default', // default/neon
// Transition style
transition: query.transition || 'linear' // default/cube/page/concave/linear(2d)
});
</script>
</body>
</html>