Let's Talk Testing

slid.es/w33ble/let-s-talk-testing

Joe Fleming

@w33ble

Node AZ

Phoenix JavaScript

Phoenix Elasticsearch Logstash and Kibana

We Will Cover

  • Why write tests
  • Terminology
  • Libraries
  • Example Tests
  • Workflow
  • Tips

Why Write Tests?

Time

  • Less breaking code
  • More Automation
  • Free Documentation

Confidence

  • Adding functionality
  • Refactoring
  • Accepting changes

Other Reasons

  • Learn codebase
  • Spec out APIs
  • Meeting customer specs

Terminology

TDD / BDD

It doesn't matter

Test Runner

  • Executable
  • Runs your tests

Test Harness

  • Executable
  • Runs your tests
  • Generates reports
  • Enables Automation

Runners and Harnesses

Assertions

     Verify output or other parameters

Suites

     Collection of tests

Testing Terms

Specs

     A single test

Fixtures

     Consistent source of data

Mocks/Stubs/Fakes

     Consistent replacement for other code

Spies

     Watch and query code execution

Testing Terms

Modules

     Pattern for grouping code into components

Dependency Injection / IoC

     Passing dependencies to consumers

Testing Terms

Code Coverage

     Amount of your code that is tests

Linting

     Detects errors and potential problems

Testing Terms

Continuous Integration

     Integrating code into a shared repo

Continuous Deployment

     Pushing working code to production

Automation Terms

Libraries

Frameworks

  • Mocha
  • Jasmine
  • TAP
  • QUnit

Assertions

  • Expect.js
  • Should.js
  • Chai

Utilities

  • Sinon - Spies and Stubs
  • Istanbul - Code Coverage
  • Phantom.js - Headless Webkit
  • Karma - Browser Runner

Example Layout

TAP


test("make sure the thingie is a thing", function (t) {
  t.equal(thingie, "thing", "thingie should be thing");
  t.deepEqual(array, ["foo", "bar"], "array has foo and bar elements");
  t.deepEqual(object, {foo: 42}, "object has foo property");
  t.type(thingie, "string", "type of thingie is string");
  t.ok(true, "this is always true");
  t.notOk(false, "this is never true");

  t.test("a child test", function (t) {
    t.equal(this, superEasy, "right!?");
  });
});

Mocha (BDD)


var expect = require('chai').expect;

describe('User', function(){
  describe('save', function(){
    it('should be a function', function () {
      expect(User).to.have.property('save');
      expect(User.save).to.be.a('function');
    });

    it('should save without error', function(done){
      var user = new User('Luna');
      user.save(function(err){
        expect(err).to.be.a('null');
        expect(user.name).to.be('Luna');

        done();
      });
    });
  });
});

Jasmine (BDD)


describe('User', function(){
  describe('save', function(){
    it('should be a function', function () {
      expect('save' in User).toBe(true);
      expect(typeof User.save).toBe('function');
    });

    it('should save without error', function(done){
      var user = new User('Luna');
      user.save(function(err){
        expect(err).toBeNull('null');
        expect(user.name).toBe('Luna');

        done();
      });
    });
  });
});

Types of Tests

Test a specific, isolated unit of code

Unit Tests

Requirements

  • Harness
  • Environment

Example Output

Example Output

Example Output

Test the integration of system components

Integration Tests

Requirements

  • Harness
  • Environment

Example Output

Example Output

WAT

Unit Tests

Test a specific, isolated unit of code

Integration Tests

Test the integration of components

  • Mocks, stubs, spies
  • Modules, DI
  • Code Separation
  • User Interaction
  • Component Separation

Workflow

"Standard"

  1. Write some code
  2. Write some tests

TDD

  1. Write some tests
  2. Write some code

Getting Started

Test Execution

  • Terminal
  • Browser
  • Selenium
  • Sauce Labs
  • Browser Stack

Test Automation

  • Build process
  • Pre-commit hooks

Automatic Local Execution

Continuous Integration

Automatic Remote Execution

  • Jenkins
  • Travis CI
  • Codeship

Continuous Deployment

Did the tests pass?

Testing Tips

Keep it small

Keep it small

Keep it modular

  • AMD / CommonJS / ES6
  • Easier separation
  • Easier inclusion in tests

Keep it modular

Keep it private

  • Don't sweat about private methods
  • Expose what you need to test

Keep it private

Keep it covered

Keep it covered

Recap

  • Small code
  • Modular code
  • Don't over-think private functions
  • Use coverage reports

Write Some Test

Some tests > No tests

Thanks!

Questions?

@w33ble

twitter:

w33ble

github:

Let's Talk Testing

By Joe Fleming

Let's Talk Testing

An attempt at making testing in Javascript more approachable

  • 2,311