Running your Tests is as easy as one of these two commands:
ember test # will run your test-suite in your current shell once
ember test --server # will run your tests on every file-change
Alternatively you can run the tests in your regular browser using the QUnit interface. Run ember server
and navigate to http://localhost:4200/tests
. In this case, the tests will run in your default environment, usually ‘development’.
The default tests in Ember CLI use the QUnit library. The included tests demonstrate how to write both unit tests and acceptance/integration tests using the new ember-testing package.
Test filenames should be suffixed with -test.js
in order to run.
If you are using Pods to organize your application, be sure to add your podModulePrefix
to the test resolver namespace.
If you have manually set the locationType in your environment.js to hash
or none
you need to update your tests/index.html
to have absolute paths (/assets/vendor.css
and /testem.js
vs the default relative paths).
ember test
will run your tests with Testem
on CI mode. You can
pass any option to Testem
using a configuration file.
If you are capturing output from the Testem
xunit reporter, use ember test --silent
to silence unwanted output such as the ember-cli version.
By default, your integration tests will run on PhantomJS. You can install via npm:
npm install -g phantomjs
We plan to make your test runner pluggable, so you can use your favorite runner.
All Ember Apps come with built-in ember test helpers,
which are useful for writing integration tests.
In order to use them, you will need to import tests/helpers/start-app.js
, which injects the required helpers.
Be sure to use the injected module
function to invoke setup
and teardown
.
1 import Ember from "ember";
2 import { test } from 'ember-qunit';
3 import startApp from '../helpers/start-app';
4 var App;
5
6 module('An Integration test', {
7 setup: function() {
8 App = startApp();
9 },
10 teardown: function() {
11 Ember.run(App, App.destroy);
12 }
13 });
14
15 test("Page contents", function() {
16 expect(2);
17 visit('/foos').then(function() {
18 equal(find('.foos-list').length, 1, "Page contains list of models");
19 equal(find('.foos-list .foo-item').length, 5, "List contains expected number of models");
20 });
21 });
An Ember CLI-generated project comes pre-loaded with ember-qunit which includes several helpers to make your unit-testing life easier, i.e.:
The generic resolver that will load what you specify. The usage closely follows QUnit’s own module
function.
Its use can be seen within the supplied index-test.js:
1 import { test, moduleFor } from 'ember-qunit';
2
3 moduleFor('route:index', "Unit - IndexRoute", {
4 // only neccessary if you want to load other items into the runtime
5 // needs: ['controller:index']
6 setup: function () {},
7 teardown: function () {}
8 });
9
10 test("it exists", function(){
11 ok(this.subject());
12 });
fullname
The resolver friendly name of the object you are testing.
description
The description that will group all subsequent tests under. Defaults to the fullname
.
callbacks
You are able to supply custom setup, teardown, & subject functionality by passing them
into the callbacks parameter. If other objects should be loaded into Ember.js, specify the objects
through the needs
property.
delegate
To manually modify the container & the testing context, supply a function as the delegate
matching this signature delegate(container, testing_context)
.
this.subject()
calls the factory for the object specified by the fullname and will return an instance of the object.
Extends the generic moduleFor
with custom loading for testing models:
1 import DS from 'ember-data';
2 import Ember from 'ember';
3 import { test, moduleForModel } from 'ember-qunit';
4
5 moduleForModel('post', 'Post Model', {
6 needs: ['model:comment']
7 });
8
9 test('Post is a valid ember-data Model', function () {
10 var store = this.store();
11 var post = this.subject({title: 'A title for a post', user: 'bob'});
12 ok(post);
13 ok(post instanceof DS.Model);
14
15 // set a relationship
16 Ember.run(function() {
17 post.set('comment', store.createRecord('comment', {}))
18 });
19
20 ok(post.get('comment'));
21 ok(post.get('comment') instanceof DS.Model);
22 });
name
The name of the model you are testing. It is necessary to only supply the name,
not the resolver path to the object(model:post
=> post
).
description
The description that will group all subsequent tests under. Defaults to the name
.
callbacks
You are able to supply custom setup, teardown, & subject functionality by passing them
into the callbacks parameter. If other objects should be loaded into Ember.js, specify
the objects through the needs
property.
Note: If the model you are testing has relationships to any other model, those must
be specified through the needs
property.
this.store()
retrieves the DS.Store
.
this.subject()
calls the factory for the DS.Model
specified by the fullname and
will return an instance of the object.
Extends the generic moduleFor
with custom loading for testing components:
1 import Ember from "ember";
2 import { test, moduleForComponent } from 'ember-qunit';
3
4 moduleForComponent('pretty-color');
5
6 test('changing colors', function(){
7 var component = this.subject();
8
9 Ember.run(function(){
10 component.set('name','red');
11 });
12
13 // first call to $() renders the component.
14 equal(this.$().attr('style'), 'color: red;');
15
16 Ember.run(function(){
17 component.set('name', 'green');
18 });
19
20 equal(this.$().attr('style'), 'color: green;');
21 });
name
The name of the component you are testing. It is necessary to only supply the name,
not the resolver path to the object(component:pretty-color
=> pretty-color
).
description
The description that will group all subsequent tests under. Defaults to the name
.
callbacks
You are able to supply custom setup, teardown, & subject functionality
by passing them into the callbacks parameter. If other objects should be loaded into Ember.js,
specify the objects through the needs
property.
this.subject()
calls the factory for the Ember.Component
specified by the fullname and
will return an instance of the object.
The first call this.$()
will render out the component. So if you want to test styling,
you must access the component via jQuery.
Ember testing provides that ability to register your own test helpers. In order to use
these with ember-cli they must be registered before startApp
is defined.
Depending on your approach, you may want to define one helper per file or a group of helpers in one file.
1 // helpers/routes-to.js
2 export default Ember.Test.registerAsyncHelper('routesTo', function (app, url, route_name) {
3 visit(url);
4 andThen(function () {
5 equal(currentRouteName(), route_name, 'Expected ' + route_name + ', got: ' + currentRouteName());
6 });
7 });
This can then be used in start-app.js, like this
1 // helpers/start-app.js
2 import routesTo from './routes-to';
3
4 export default function startApp(attrs) {
5 //...
An alternative approach is to create a bunch of helpers wrapped in a self calling function, like this
1 // helpers/custom-helpers.js
2 var customHelpers = function() {
3 Ember.Test.registerHelper('myGreatHelper', function (app) {
4 //do awesome test stuff
5 });
6
7 Ember.Test.registerAsyncHelper('myGreatAsyncHelper', function (app) {
8 //do awesome test stuff
9 });
10 }();
11
12 export default customHelpers;
which can be used in start-app.js
1 // helpers/start-app.js
2 import customHelpers from './custom-helpers';
3
4 export default function startApp(attrs) {
5 //...
Once your helpers are defined, you’ll want to ensure that they are listing in the .jshintrc file within the test directory.
1 // /tests/.jshintrc
2 {
3 "predef": [
4 "document",
5 //...
6 "myGreatHelper",
7 "myGreatAsyncHelper"