Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing - The Next Frontier
Search
Robert Jackson
March 10, 2016
Programming
1
66
Testing - The Next Frontier
Talk given at the Boston Ember meetup on 2016-03-10.
Robert Jackson
March 10, 2016
Tweet
Share
More Decks by Robert Jackson
See All by Robert Jackson
😂 of TypeScript
rwjblue
0
340
Testing: The Modern Way
rwjblue
0
40
Glimmer ✨ as a Gateway to Ember 🐹
rwjblue
0
59
Testing: The Future... Today?
rwjblue
0
61
Rails Developer's Intro to Ember
rwjblue
1
180
A tale of two pods
rwjblue
3
830
Ember 2.0 - RFC Recap
rwjblue
6
670
Ember CLI Addons
rwjblue
7
800
RAILS + EMBER.JS + EMBER-CLI = ❤
rwjblue
10
1.8k
Other Decks in Programming
See All in Programming
明示と暗黙 ー PHPとGoの インターフェイスの違いを知る
shimabox
2
540
AIエージェントはこう育てる - GitHub Copilot Agentとチームの共進化サイクル
koboriakira
0
600
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
270
iOS 26にアップデートすると実機でのHot Reloadができない?
umigishiaoi
0
130
The Niche of CDK Grant オブジェクトって何者?/the-niche-of-cdk-what-isgrant-object
hassaku63
1
360
A full stack side project webapp all in Kotlin (KotlinConf 2025)
dankim
0
130
PipeCDのプラグイン化で目指すところ
warashi
1
290
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
130
Node-RED を(HTTP で)つなげる MCP サーバーを作ってみた
highu
0
120
Result型で“失敗”を型にするPHPコードの書き方
kajitack
5
960
What's new in AppKit on macOS 26
1024jp
0
130
The Modern View Layer Rails Deserves: A Vision For 2025 And Beyond @ RailsConf 2025, Philadelphia, PA
marcoroth
2
570
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
20
1.3k
Docker and Python
trallard
44
3.5k
Rails Girls Zürich Keynote
gr2m
95
14k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Raft: Consensus for Rubyists
vanstee
140
7k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Transcript
Testing: The Next Frontier?
None
Who the heck is this guy? • Ember Core Team
• Twitch • General Open Source Addict twitter: rwjblue github: rwjblue
Thank You!!
What are we talking about?
State of Testing Today • Acceptance • Integration • Unit
Acceptance moduleForAcceptance('Acceptance | login'); test('visiting /login', function(assert) { visit('/login'); andThen(function()
{ assert.equal(currentURL(), '/login'); }); });
Integration moduleForComponent('pretty-color', { integration: true }); test('button click', function(assert) {
this.render(hbs`{{magic-title}}`); this.$('button').click(); assert.equal(this.$().text(), 'This is Magic'); });
Unit moduleFor('route:application'); test('perform the right query', function(assert) { let route
= this.subject(); let result = route._queryString(); assert.equal(result, '?awesome=sauce'); });
Great, :shipit:
The End
Seriously?
• Built for a globals world. • “magic” `andThen` •
No ability to stub/mock services. Acceptance Test Issues
None
• Completely ignorant about async • Manual triggering of user
interaction • Much less “tailored” API Unit/Integration Test Issues
None
Now what?
emberjs/rfcs#119
• Use `async` / `await` • Consistent interface • Extendability
• Backwards Compatibility Grand Testing Unification
None
None
None
Acceptance moduleForAcceptance('Can see things'); test('clicking redirects', async function(assert) { await
visit('/things'); let list = find('.thing-item'); assert.equal(list.length, 5); await click('.thing-item[data-id=1]'); assert.equal(this.currentRouteName, 'other- thing'); });
Integration moduleForIntegration('post-display'); test('expand when clicked', async function(assert) { await render(hbs`{{post-display}}`);
await click('.post-item'); assert.equal( this.find('.post-created-at').textContent, '2016-01-05' ); });
• Overriding a service • Registering custom test helpers •
Registering custom waiters • Accessing service instances General Testing Concerns
• Hooks for work before/after tests. • Accessing general test
information General Testing Concerns
Overriding a Service import Mock from 'somewhere/else'; moduleForAcceptance('something', { beforeEach()
{ this.owner.register('service:stripe', Mock); } });
Registering Custom Helpers import selectCategory from '../helpers/select-category'; import loginAsAdmin from
'../helpers/login-as-admin'; moduleForAcceptance('Can see things', { beforeEach() { this.registerHelpers({ loginAsAdmin, selectCategory }); } });
Custom Helpers // tests/helpers/login-as-admin'; import { testHelper } from 'ember-qunit';
export default testHelper(async function() { await this.click('.login-now'); await this.fillIn('.username', 'rwjblue'); await this.fillIn('.password', 'moar beerz plz'); await this.click('.submit'); });
Custom Helpers import selectCategory from '../helpers/select-category'; import loginAsAdmin from '../helpers/login-as-admin';
moduleForAcceptance('Can see things', { beforeEach() { this.registerHelpers({ loginAsAdmin, selectCategory }); } });
Custom Waiters import { testWaiter } from 'ember-test-helpers'; import {
hasPendingTransactions } from 'app- name/services/transactions'; export default testWaiter(function() { return hasPendingTransactions(); });
Custom Waiters import transactionWaiter from '../waiters/pending-transactions'; test('stuff happens', async function(assert)
{ // Normally done in setup, but slides.... this.registerWaiter(transactionWaiter); await click('.foo'); // all pending transactions are completed here... });
Accessing Services test('foo', function(assert) { this.store = this.owner.lookup('service:store'); this.store.push(....); });
General Hooks // */tests/configuration.js import { TestConfig } from 'ember-test-helpers';
export default class extends TestConfig { beforeSuite() {} beforeEach(testType, testContext) {} afterEach(testType, testContext) {} }
General Hooks // liquid-fire's addon-test-support/configuration.js import { TestConfig } from
'ember-test-helpers'; import runningTransitionWaiter from './waiters/running-transition'; import randoHelper from './helpers/rando'; export default class extends TestConfig { beforeEach() { this.registerWaiter(runningTransitionWaiter); this.registerHelper('randoHelper', randoHelper); } }
General Hooks // mirage's addon-test-support/configuration.js import { TestConfig } from
'ember-test-helpers'; import setup from 'ember-cli-mirage/setup-server'; export default class extends TestConfiguration { beforeEach() { this.server = setup(this.owner); } }
Test Information import { testHelper } from 'ember-qunit'; export default
testHelper(function() { if (this.testInfo.type === 'acceptance') { // acceptance test stuff here } else { // integration/unit test stuff here } });
The End