Slide 1

Slide 1 text

Let’s Get Testable! An Introduction to Unit Testing

Slide 2

Slide 2 text

Prologue

Slide 3

Slide 3 text

We make more than “websites”
 now.

Slide 4

Slide 4 text

Back-end practices are influencing our path.

Slide 5

Slide 5 text

And along comes testing.

Slide 6

Slide 6 text

Unit Testing

Slide 7

Slide 7 text

“Units” are small pieces of code, typically at the function level.

Slide 8

Slide 8 text

Validate an email address Perform a calculation Set user information

Slide 9

Slide 9 text

Unit tests help prevent regressions.

Slide 10

Slide 10 text

Unit tests document your code.

Slide 11

Slide 11 text

Test-Driven Development

Slide 12

Slide 12 text

You need team buy-in.

Slide 13

Slide 13 text

Popular Tools • Jasmine (http://jasmine.github.io/) • Mocha (http://visionmedia.github.io/mocha/) • QUnit (http://qunitjs.com/) • CasperJS (http://casperjs.org/) • …and others!

Slide 14

Slide 14 text

An example. (We’ll be using Jasmine.)

Slide 15

Slide 15 text

A calculator app.

Slide 16

Slide 16 text

Describe Your Test Suite describe(“Calculator Operations”, function () {! ! });

Slide 17

Slide 17 text

Write A Test Description describe(“Calculator Operations”, function () {! ! ! it(“Should add two numbers”, function () {! ! ! });! ! });

Slide 18

Slide 18 text

Expectations and Matchers describe(“Calculator Operations”, function () {! ! ! it(“Should add two numbers”, function () {! ! ! ! Calculator.init();! ! ! ! ! ! var result = Calculator.addNumbers(7,3);! ! ! ! expect(result).toBe(10);! ! ! });! ! });

Slide 19

Slide 19 text

Expectations and Matchers describe(“Calculator Operations”, function () {! ! ! it(“Should add two numbers”, function () {! ! ! ! Calculator.init();! ! ! ! ! ! var result = Calculator.addNumbers(7,3);! ! ! ! expect(result).toBe(10);! ! ! expect(result).not.toBe(null);! ! ! });! ! });

Slide 20

Slide 20 text

Add More Tests … ! it(“Should add two numbers”, function () {! ! ! Calculator.init();! ! ! ! var result = Calculator.addNumbers(7,3);! ! ! ! expect(result).toBe(10);! ! ! expect(result).not.toBe(null);! ! });! ! ! it(“Should subtract two numbers”, function () {! ! ! Calculator.init();! ! ! ! var result = Calculator.subtractNumbers(20,4);! ! ! ! expect(result).toBe(16);! ! ! expect(result).not.toBe(null);! ! });! …

Slide 21

Slide 21 text

Hmm… … ! it(“Should add two numbers”, function () {! ! ! Calculator.init();! ! ! ! var result = Calculator.addNumbers(7,3);! ! ! ! expect(result).toBe(10);! ! ! expect(result).not.toBe(null);! ! });! ! ! it(“Should subtract two numbers”, function () {! ! ! Calculator.init();! ! ! ! var result = Calculator.subtractNumbers(20,4);! ! ! ! expect(result).toBe(16);! ! ! expect(result).not.toBe(null);! ! });! …

Slide 22

Slide 22 text

Setup and Breakdown describe(“Calculator Operations”, function () {! ! ! beforeEach(function () {! ! ! ! ! ! Calculator.init();! ! ! });! ! });

Slide 23

Slide 23 text

Setup and Breakdown describe(“Calculator Operations”, function () {! ! ! beforeEach(function () {! ! ! ! ! ! Calculator.init();! ! ! });! ! ! afterEach(function () {! ! ! ! ! ! Calculator.remove();! ! ! });! ! });

Slide 24

Slide 24 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! });! …

Slide 25

Slide 25 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! });! …

Slide 26

Slide 26 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! });! …

Slide 27

Slide 27 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! ! Calculator.addNumbers(7,10);! ! ! ! expect(Calculator.updateCurrentValue).toHaveBeenCalled();! ! ! });! …

Slide 28

Slide 28 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! ! Calculator.addNumbers(7,10);! ! ! ! expect(Calculator.updateCurrentValue).toHaveBeenCalled();! ! ! ! ! ! expect(Calculator.updateCurrentValue)! ! ! ! ! .toHaveBeenCalledWith(17);! ! ! });! …

Slide 29

Slide 29 text

Spies … ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! ! Calculator.addNumbers(7,10);! ! ! ! expect(Calculator.updateCurrentValue).toHaveBeenCalled();! ! ! ! ! ! expect(Calculator.updateCurrentValue)! ! ! ! ! .toHaveBeenCalledWith(17);! ! ! ! expect(Calculator.currentValue).toBe(17);! ! ! });! …

Slide 30

Slide 30 text

Asynchronous Operations

Slide 31

Slide 31 text

.done() … ! it(“Should test async”, function (done) {! ! ! ! ! ! var foo = 0;! ! ! foo++;! ! ! ! setTimeout(function () {! ! ! ! expect(foo).toBe(1);! ! ! ! done();! ! ! }, 100);! ! ! });! …

Slide 32

Slide 32 text

.done() … ! ! ! beforeEach(function (done) {! ! ! ! ! ! Calculator.setUserInfo(“aliciasedlock”);! ! ! ! setTimeout(function () {! ! ! ! done();! ! ! }, 4000);! ! ! });! ! ! it(“Should set the user information”, function () {! ! ! ! ! ! expect(Calculator.user).toBe(“Alicia”);! ! ! });! …

Slide 33

Slide 33 text

.done() … ! ! ! beforeEach(function (done) {! ! ! ! ! ! jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;! ! ! ! ! Calculator.setUserInfo(“aliciasedlock”);! ! ! ! setTimeout(function () {! ! ! ! done();! ! ! }, 9000);! ! ! });! ! ! it(“Should set the user information”, function () {! ! ! ! ! ! expect(Calculator.user).toBe(“Alicia”);! ! ! });! …

Slide 34

Slide 34 text

Should I or Shouldn’t I…?

Slide 35

Slide 35 text

… ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! ! Calculator.addNumbers(7,10);! ! ! ! expect(Calculator.updateCurrentValue).toHaveBeenCalled();! ! ! ! ! ! expect(Calculator.updateCurrentValue)! ! ! ! ! .toHaveBeenCalledWith(17);! ! ! ! expect(Calculator.currentValue).toBe(17);! ! ! });! …

Slide 36

Slide 36 text

… ! it(“Should store the results of operations”, function () {! ! ! ! expect(Calculator.currentValue).toBe(0);! ! ! ! spyOn(Calculator, “updateCurrentValue”);! ! ! ! Calculator.addNumbers(7,10);! ! ! ! var result = $(“span#result”).text();! ! ! ! expect(result).toBe(“17”);! ! });! …

Slide 37

Slide 37 text

Testing Code vs. Testing jQuery

Slide 38

Slide 38 text

And if I already have an app?

Slide 39

Slide 39 text

• As your modify code, write a test.

Slide 40

Slide 40 text

• As your modify code, write a test. • Adding new features? Write tests!

Slide 41

Slide 41 text

• As your modify code, write a test. • Adding new features? Write tests! • Incorporate into code reviews.

Slide 42

Slide 42 text

End-To-End Testing

Slide 43

Slide 43 text

Can a user get from point A to point B?

Slide 44

Slide 44 text

Registration flow Checkout process Credential-specific functionality

Slide 45

Slide 45 text

Automated Testing for QA

Slide 46

Slide 46 text

Real Browser vs. Headless Browser

Slide 47

Slide 47 text

Real Browser • Selenium (http://www.seleniumhq.org/) • Karma (http://karma-runner.github.io/0.12/index.html)

Slide 48

Slide 48 text

Headless Browser • Karma (http://karma-runner.github.io/0.12/index.html) • PhantomJS (http://phantomjs.org/)

Slide 49

Slide 49 text

“CSS Testing”…?

Slide 50

Slide 50 text

We Could Mean… • Styling consistency • Malformed/unused CSS • CSS Regressions

Slide 51

Slide 51 text

Styling Consistency • Object-Oriented CSS/Modular Development • SASS/LESS • Pattern Libraries/Living Style Guides

Slide 52

Slide 52 text

Malformed/unused CSS • CSS code styling guide (http://cssguidelin.es/) • CSS Lint (https://github.com/CSSLint/csslint) • UnCSS (https://github.com/giakki/uncss)

Slide 53

Slide 53 text

CSS Regression Testing?

Slide 54

Slide 54 text

CSS Regression Tools • Wraith (https://github.com/BBC-News/wraith) • Resemble.js (http://huddle.github.io/Resemble.js/) • …plus PhantomCSS • …plus CasperJS

Slide 55

Slide 55 text

This can help with RWD testing.

Slide 56

Slide 56 text

This concept is still very young.

Slide 57

Slide 57 text

We can define what CSS testing means, if we want it.

Slide 58

Slide 58 text

Epilogue

Slide 59

Slide 59 text

1. It takes time.

Slide 60

Slide 60 text

2. Test time matters

Slide 61

Slide 61 text

3. You will still have bugs

Slide 62

Slide 62 text

4. Lots of build tool integrations!

Slide 63

Slide 63 text

5. Always keep improving

Slide 64

Slide 64 text

Thank you JS Summit! Follow @aliciability for slides