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-qunitmoduleFormoduleForComponentmoduleForModelember-mochasetupTestsetupComponentTestsetupModelTest
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-sourceember-dataember-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).