learn frontend testing

47
LEARN FRONTEND TESTING - SEATTLE JS OCT. 16TH, 2013 | Ryan Roemer @ryan_roemer @FormidableLabs

Upload: ryan-roemer

Post on 28-Nov-2014

3.925 views

Category:

Technology


1 download

DESCRIPTION

Are you writing enough tests for your applications? We thought not! Ryan Roemer of Formidable Labs and author of the new book, "Backbone Testing.js", will help us learn how to test your JavaScript applications in a 3 hour workshop at Redfin's beautiful downtown headquarters. The workshop will be a mixture of lecture and hands on lessons. With the help of our fabulous mentors you'll learn how to craft a frontend test infrastructure using Mocha, Chai, Sinon.JS and PhantomJS.

TRANSCRIPT

Page 2: Learn Frontend Testing

SPONSORS

Page 7: Learn Frontend Testing

MENTORSTry to keep pace with the presentation,but side conversations are encouraged

and don't let us stop any gooddirections.

And, thanks!

Page 8: Learn Frontend Testing

MOTIVATIONWeb applications are increasingly

becoming frontend heavy.

We need to verify app logic andbehavior, and that means braving the

browser.

Page 9: Learn Frontend Testing

SO LET'S TESTBackend is straightforward and easy

... but what about the frontend?

Page 10: Learn Frontend Testing

FRONTEND TESTINGFrontend testing is difficult and error-

prone.

Asynchronous events, timing

Browser idiosyncracies

State of testing technologies

Page 11: Learn Frontend Testing

BUT GETTING BETTER

Page 12: Learn Frontend Testing

... so let's get started with a modernfrontend test stack.

Page 13: Learn Frontend Testing

GET THE CODEgithub.com/FormidableLabs/learn-frontend-

testing$ git clone https://github.com/FormidableLabs/ learn-frontend-testing.git

Page 14: Learn Frontend Testing

OVERVIEWInstallation and test page

Suites

Assertions

Fakes

Automation

Page 15: Learn Frontend Testing

WE WILL LEARN HOW TOHook frontend JS to tests

Write assertions against behavior

Fake application behavior

Run and verify the tests

Page 16: Learn Frontend Testing

THINGS WE'RE NOTGOING TO COVER

TDD / BDD

Application development

Functional testing

Performance testing

Page 17: Learn Frontend Testing

CODING TIMEWe're going to say hello:

"SeattleJS" ➞ "Hello SeattleJS!"

And strings:camel case

"fun-test-time" ➞ "funTestTime"

Page 18: Learn Frontend Testing

SET UP YOUR PROJECT# Copy the skeleton application.$ cp -r skeleton MY_APP_NAME

Page 19: Learn Frontend Testing

PROJECT STRUCTUREUsing with the "skeleton" application.

MY_APP_NAME/ js/ app/ hello.js camel.js lib/ chai.js mocha.js mocha.css sinon.js index.html

Page 20: Learn Frontend Testing

HELLO!skeleton/js/app/hello.js

// Hello [VALUE]!var hello = function (val) { return "Hello " + val + "!";};

Page 21: Learn Frontend Testing

CAMEL CASEskeleton/js/app/camel.js

// Camel case a string.var camel = function (val) { // Uppercase the first character after a dash. return val.replace(/-(.)/g, function (m, first) return first.toUpperCase(); });};

Page 22: Learn Frontend Testing

DEMOskeleton/index.html

Page 23: Learn Frontend Testing

TEST HARNESS

Page 24: Learn Frontend Testing

TEST LIBRARIES (v1.13.0): Framework

(v1.7.3): Assertions

(v1.8.1): Fakes - spies and stubs

Mocha

Chai

Sinon.JS

Page 25: Learn Frontend Testing

DIRECTORY LAYOUTA combined structure.

MY_APP_NAME/ js/ app/ lib/ spec/ hello.spec.js *.spec.js test.html index.html

Page 26: Learn Frontend Testing

THE TEST PAGECreate a test "driver" web page.

example/test.html$ touch MY_APP_NAME/test.html

Page 27: Learn Frontend Testing

TEST.HTML<html> <head> <title>Frontend Testing</title> <!-- Application libraries. --> <script src="js/app/hello.js"></script> <script src="js/app/camel.js"></script> <!-- Test styles and libraries. --> <link rel="stylesheet" href="js/lib/mocha.css" /> <script src="js/lib/mocha.js"></script> <script src="js/lib/chai.js"></script> <script src="js/lib/sinon.js"></script>

Page 28: Learn Frontend Testing

TEST.HTML <!-- Test Setup --> <script>

</script>

// Set up Chai and Mocha. window.expect = chai.expect; mocha.setup("bdd"); // Run tests on window load. window.onload = function () { mocha.run();

Page 29: Learn Frontend Testing

TEST.HTML <!-- Tests. --> <!-- ... spec script includes go here ... --> </head> <body> <div id="mocha"></div> </body></html>

example/test-empty.html

Page 30: Learn Frontend Testing

MOCHA SUITES, SPECSSpec: A test.

Suite: A collection of specs or suites.

Page 31: Learn Frontend Testing

SUITES, SPECS | test-mocha.html mocha-suite.spec.js

describe("single level", function () { it("should test something");});

describe("top-level", function () { describe("nested", function () { it("is slow and async", function (done) { setTimeout(function () { done(); }, 300); }); });});

Page 32: Learn Frontend Testing

SETUP, TEARDOWN | test-mocha.html mocha-

setup.spec.jsdescribe("setup/teardown", function () { before(function (done) { done(); }); beforeEach(function () {});

after(function (done) { done(); }); afterEach(function () {});

it("should test something");});

Page 33: Learn Frontend Testing

CHAI ASSERTIONSNatural language syntax.

Chained assertions.

Page 34: Learn Frontend Testing

CHAI APIThe :"bdd" API

Chains: to, be, been, have

Groups: and

Basics: a, equal, length, match

Page 35: Learn Frontend Testing

HELLO! | test-hello.html hello.spec.js

describe("hello", function () { it("should say hello", function () { expect(hello("World")) .to.be.a("string").and .to.equal("Hello World!").and .to.have.length(12).and .to.match(/He[l]{2}/); });});

Page 36: Learn Frontend Testing

CAMEL CASE | test-camel.html camel.spec.js

describe("camel", function () { it("handles base cases", function () { expect(camel("")).to.equal(""); expect(camel("single")).to.equal("single"); }); it("handles dashed cases", function () { expect(camel("a-b-c")).to.equal("aBC"); expect(camel("one-two")).to.equal("oneTwo" });});

Page 37: Learn Frontend Testing

MORE CHAI | | test-chai.html chai.spec.js chai-

fail.spec.jsdescribe("chai", function () { it("asserts", function () { expect(["one", "two"]).to.contain("two"); expect({foo: {bar: 12}}) .to.have.deep.property("foo.bar", 12); });});describe("chai", function () { it("fails", function () { expect("one").to.equal("two"); });

Page 38: Learn Frontend Testing

SINON.JS FAKESDependencies, complexities? Fake it!

: Observe function behavior.

: Spies that replace behavior.

: Override $.ajax, etc.

Spies

Stubs

Fake Server

Page 39: Learn Frontend Testing

SINON.JS SPY | |test-sinon.html camel-spy.spec.js

camel.jsdescribe("camel", function () { it("spies upper case", function () { var spy = sinon.spy(String.prototype, "toUpperCase"

expect(spy.callCount).to.equal(0); expect(camel("a-b")).to.equal("aB"); expect(spy.callCount).to.equal(1); expect(spy.firstCall.returnValue).to.equal(

spy.restore(); });

Page 40: Learn Frontend Testing

SINON.JS STUB | |test-sinon.html camel-stub.spec.js

camel.jsdescribe("camel", function () { it("stubs upper case", function () { var stub = sinon.stub(String.prototype, "toUpperCase" function () { return "FOO"; });

expect(camel("a-b")).to.equal("aFOO"); expect(stub.callCount).to.equal(1);

stub.restore(); });});

Page 41: Learn Frontend Testing

AUTOMATIONDrive our frontend tests with

using PhantomJS Mocha-PhantomJS

Page 42: Learn Frontend Testing

PREP TEST.HTMLUpdate the file:test.html

window.onload = function () { (window.mochaPhantomJS || mocha).run();};

Page 43: Learn Frontend Testing

HEADLESS!Install and drive from the

command line:tests

$ npm install mocha-phantomjs$ node_modules/.bin/mocha-phantomjs \ MY_APP_NAME/test.html

Page 44: Learn Frontend Testing

... and that's all for now!

Page 45: Learn Frontend Testing

WHAT WE'VE COVEREDTest harness

Suites, specs

Assertions

Fakes

Automation

Page 46: Learn Frontend Testing

ADDITIONAL TOPICSAdvanced testing: DOM, fixtures

TDD / BDD

Functional testing

Performance testing

Continuous Integration: ( )Travis CI