Test like a pro with Ember.js

Preview:

Citation preview

Test like a pro

Mike North - Silicon Valley Ember.js Meetup - April 30, 2015

@MichaelLNorth2

Mike North

@MichaelLNorth

The Plan

3

Testing Basics

Test types

Test technology

Testing with Ember

Test helpers

Simulating an API

Lessons learned @

Yahoo

Test Automation

Continuous Integration

Cross-Device testing

Testing Basics

@MichaelLNorth

Unit tests

5

Fast & Focused

Isolated

Excellent at testing

“algorithmic complexity”

Functional tests

(a.k.a. “acceptance tests)

Test behavior in context

Simulate user behavior

Often based on specs or

acceptance criteria

Integration tests

Ensure that contracts at

integration points stay in

place

NOT functional tests

“End to end test”

Check for multi-

component system

integrity

Usually very slow

@MichaelLNorth

Test types - how to test a….

6

Algorithm Unit Test

Acceptance Criteria Acceptance/Functional Test

Workflow Acceptance/Functional Test

Contract between two

components

Integration test

Total System Integrity “End to end” test

Testing with Ember

8

Testing with Ember - QUnit Modules

import Ember from 'ember';

import startApp from '../../tests/helpers/start-

app';

import { test } from 'ember-qunit';

var App;

module('Acceptance - Loader', {

beforeEach() { App = startApp(); },

afterEach() { Ember.run(App, 'destroy'); }

});

test("Load the page I'm testing", assert => {

visit('/loader');

assert.equal(Ember.$('.loader').length, 0,

'No loader showing');

click('.stop-loader-button');

andThen(() => {

assert.equal(Ember.$('.loader').length, 0,

'No loader showing');

});

});

per-test setup

and teardown

hooks

9

Testing with Ember - ember-test-helpers modules

moduleFor(name [, description [, callbacks]])

moduleForModel( … )

moduleForComponent( … )

• Setup an empty container to unit test in isolation

• Set context of view, so bindings work

moduleForComponent('my-tabs', {

needs: ['component:my-tab']

});

@MichaelLNorth

Testing with Ember - Integration Test Helpers

10

visit(url)

fillIn(selector, text)

click(selector)

keyEvent(sel, type, key)

triggerEvent(sel, type, opts)

find(selector, content)

currentPath()

currentRouteName()

currentURL()

Async Sync

@MichaelLNorth

An example

11

Router.map(() => {

this.resource('lists', () => {

this.route('index', {path: '/'});

});

this.resource('list', {path: 'list/:id'}, () => {

this.route('show', {path: '/'});

});

});

router.js

@MichaelLNorth

Steps

Testing with Ember - Integration Test Helpers - Async

12

test('Drilling into a shopping list from the index page', assert => {

visit('/lists');

andThen(() => {

assert.equal(

currentURL(), ‘/lists',

'Should be at the index page’

);

assert.equal(

find('.list-of-lists .list-item').length, 2,

'Two shopping lists are in the index’

);

});

click('.list-of-lists .list-item:nth-child(1)');

andThen(() => {

assert.equal(currentURL(), ‘/list/1’,

'Showing the first shopping list’

);

});

console.log('Hello world!');

});

@MichaelLNorth

Testing with Ember - Simulating an API

13

trek/fakehr trek/pretender

• Resolve a pending request • Set up a fake “server”

/api/lines

/api/items?ids[]=1&ids[]=2&ids[]=3

"items": [

{"id": 1, "name": "Apple", "list": 1},

{"id": 2, "name": "Pear", "list": 1},

{"id": 3, "name": "Grape", "list": 1}

]

"lists": [

{"id": 1, "name": "Fruit", "items": [1, 2, 3]},

{"id": 2, "name": "Vegetables", "items": [4, 5, 6]}

]

@MichaelLNorth

Testing with Ember - Simulating an API

14

trek/fakehr trek/pretender

@MichaelLNorth

Testing with Ember - Simulating an API

15

/api/lines

/api/lines/1/items

trek/fakehr

Continuous Integration

@MichaelLNorth

Continuous Integration

17

Clone

Checkout

before_install

install

before_script

script

after_success after_failure

after_scriptnpm install; bower

install

ember test ci

setup phantomjs

2.0

mark PR

“ok”

mark PR

“failed”

@MichaelLNorth

Continuous Integration

w/ ember-try

18

kategengler/ember-try

env:

matrix:

- EMBER_TRY_SCENARIO=default

- EMBER_TRY_SCENARIO=ember-release

- EMBER_TRY_SCENARIO=ember-beta

- EMBER_TRY_SCENARIO=ember-canary

.travis.yml

matrix:

fast_finish: true

allow_failures:

- env: EMBER_TRY_SCENARIO=ember-canary

Build has passed, but this is still running!

@MichaelLNorth

Cross-Device Testing

w/ ember-cli-sauce

19

johanneswuerbach/ember-cli-sauce

@MichaelLNorth

Cross-Device Testing

w/ ember-cli-sauce

20

PROTIP: You may need to fiddle with

testem port and/or hostname to get OS X

working

{

"framework": "qunit",

"host": "lvh.me",

"port": "7000",

"test_page": "tests/index.html?hidepassed",

...

}

@MichaelLNorth21

$0

for open

source