Summary
In order to largely reduce the brittleness of tests, this RFC proposes to remove the concept of artificially restricting the resolver used under testing.
Motivation
Disabling the resolver while running tests leads to extremely brittle tests.
It is not possible for collaborators to be added to the object (or one of its dependencies) under test, without modifying the test itself (even if exactly the same API is exposed).
The ability to restrict the resolver is not actually a feature of Ember's container/registry/resolver system, and has posed as significant maintenance challenge throughout the lifetime of ember-test-helpers.
Removing this system of restriction will make choosing what kind of test to be used easier, simplify many of the blueprints, and enable much simpler refactoring of an applications components/controllers/routes/etc to use collaborating utilties and services.
Transition Path
Deprecate Functionality
Issue a deprecation if integration: true
is not included in the specified
options for the APIs listed below. This specifically includes specifying
unit: true
, needs: []
, or specifying none of the "test type options"
(unit
, needs
, or integration
options) to the following ember-qunit
and ember-mocha
API's:
ember-qunit
moduleFor
moduleForComponent
moduleForModel
ember-mocha
setupTest
setupComponentTest
setupModelTest
Non Component Test APIs
The migration path for moduleFor
, moduleForModel
, setupTest
, and
setupModelTest
is very simple:
// ember-qunit
// before
moduleFor('service:session');
moduleFor('service:session', {
unit: true
});
moduleFor('service:session', {
needs: ['type:thing']
});
// after
moduleFor('service:session', {
integration: true
});
// ember-mocha
// before
describe('Session Service', function() {
setupTest('service:session');
// ...snip...
});
describe('Session Service', function() {
setupTest('service:session', { unit: true });
// ...snip...
});
describe('Session Service', function() {
setupTest('service:session', { needs: [] });
// ...snip...
});
// after
describe('Session Service', function() {
setupTest('service:session', { integration: true });
// ...snip...
});
The main change is adding integration: true
to options (and removing unit
or needs
if present).
Component Test APIs
Implicitly relying on "unit test mode" has been deprecated for quite some time
(introduced 2015-04-07),
so all consumers of moduleForComponent
and setupComponentTest
are specifying
one of the "test type options" (unit
, needs
, or integration
).
This RFC proposes to deprecate completely using unit
or needs
options with
moduleForComponent
and setupComponentTest
. The vast majority of component tests
should be testing via moduleForComponent
/ setupComponentTest
with the integration: true
option set, but on some rare occaisions it is easier to use the "unit test" style is
desired (e.g. non-rendering test) these tests should be migrated to using moduleFor
/ setupTest
directly.
// ember-qunit
// before
moduleForComponent('display-page', {
unit: true
});
moduleForComponent('display-page', {
needs: ['type:thing']
});
// after
moduleFor('component:display-page', {
integration: true
});
// ember-mocha
describe('DisplayPageComponent', function() {
setupComponentTest('display-page', { unit: true });
// ...snip...
});
describe('DisplayPageComponent', function() {
setupComponentTest('display-page', { needs: [] });
// ...snip...
});
// after
describe('DisplayPageComponent', function() {
setupTest('component:display-page', { integration: true });
// ...snip...
});
Ecosystem Updates
The blueprints in all official projects (and any provided by popular addons) will need to be updated to avoid triggering a deprecation.
This includes:
ember-source
ember-data
ember-cli-legacy-blueprints
- Others?
Remove Deprecated unit
/ needs
Options
Once the changes from this RFC are made, we will be able to remove
support for the unit
and needs
options from ember-test-helpers
,
ember-qunit
, and ember-mocha
. This would be a "semver major"
version bump for all of the related libraries to properly signal that
functionality was removed.
Once the underlying libraries have done a major version bump, we will
introduce a deprecation for using the integration
option. This
deprecation would be issued once for the entire test suite (not once
per test module which has integration
passed in). We will also update
the blueprints to remove the extraneous integration
option.
How We Teach This
This RFC would require an audit of the main Ember.js guides to ensure that all usages of the APIs in question continue to be non-deprecated valid usages.
Drawbacks
Churn
One drawback to this deprecation proposal is the churn associated with modifying the options passed for each test. This can almost certainly be mitigated by providing a codemod to enable automated updating.
There are additional changes being entertained that would require changes for the default testing blueprints, we should ensure that these RFCs do not conflict or cause undue churn/pain.
integration: true
Confusion
Prior to this deprecation we had essentially 4 options for testing components:
moduleFor(..., { unit: true })
moduleFor(..., { integration: true })
moduleForComponent(..., { unit: true })
moduleForComponent(..., { integatrion: true })
With this RFC the option integration
no longer provides value (we aren't talking
about "unit" vs "integration" tests), and may be seen as confusing.
I believe that this concern is mitigated by the ultimate removal of the integration
(it is only required in order to allow us a path forward that is compatible with
todays ember-qunit/ember-mocha versions).