I'm using Yeoman and generator-angular to manage AngularJS apps, but I'm having trouble with automated testing.
Running grunt test
will run unit tests once. I can get E2E tests to run after unit tests by altering the karma config block in Gruntfile.js
, adding e2e:
karma: {
//...
e2e: {
configFile: 'karma-e2e.conf.js',
singleRun: true
}
},
Great: now when I type grunt test
all tests are run. But they're only run one time, and there's a big overhead (starting compass, running the server, launching the Chrome processes, etc.). Instead, the server and Chrome processes should remain running and, when I save a test, tests should be re-run.
I can achieve this by modifying both karma.conf.js
and karma-e2e.conf.js
and setting singleRun = true
, then running karma start
in one terminal pane, and karma start karma-e2e.conf.js
in another. Provided none of the ports in the karma configs conflict (which they do by default), this works. Now I'm bypassing Grunt and just doing my own thing (which seems a little silly, as Grunt is supposed to make things easier).
Anyway, after a few more changes (fixes?) — not detailed for brevity — this works but doesn't cut it: I now have to run two different commands and keep an eye on two different terminal panes. Surely there's a better way.
How can I run a single command to watch my test files and re-run tests appropriately?
Bonus question: why on Earth is this functionality not provided as is? Is it just a question of the developer(s) of generator-angular not having enough time to implement this stuff? I ask because I'm only just getting into Angular/Yeoman/Karma (as you probably noticed), and feel that automated testing of both E2E and unit tests are crucial to workflow.
As I mentioned in a comment to your question - PhantomJS saves a lot of hassle. That aside, I believe you can handle everything from within your Gruntfile and just continue to run grunt test
to start the whole thing.
grunt-karma allows full customization of your karma options with some handy add-ons.
From the docs:
....
You can override any of the config file's settings directly:
karma: {
unit: {
configFile: 'karma.conf.js',
runnerPort: 9999,
singleRun: true,
browsers: ['PhantomJS']
}
}
Sharing Configs
If you have multiple targets, it may be helpful to share common
configuration settings between them. Grunt-karma supports this by
using the options property:
karma: {
options: {
configFile: 'karma.conf.js',
runnerPort: 9999,
browsers: ['Chrome', 'Firefox']
},
continuous: {
singleRun: true
browsers: ['PhantomJS']
},
dev: {
reporters: 'dots'
}
}
Additionally you may want to snoop around in Yeoman's generator-angular Gruntfile code to see what else may be available or at least mockable.
You can try this to run only e2e tests
grunt karma:e2e
Within the karma.conf.js file (approx line:38) find autoWatch = false; and change it to true.
Now if you run grunt karma:unit you will find that it leaves the test server running and any changes to project files immediately run the tests again.
//
// test/midway/appSpec.js
//
describe("Midway: Testing Modules", function() {
describe("App Module:", function() {
var module;
before(function() {
module = angular.module("App");
});
it("should be registered", function() {
expect(module).not.to.equal(null);
});
describe("Dependencies:", function() {
var deps;
var hasModule = function(m) {
return deps.indexOf(m) >= 0;
};
before(function() {
deps = module.value('appName').requires;
});
//you can also test the module's dependencies
it("should have App.Controllers as a dependency", function() {
expect(hasModule('App.Controllers')).to.equal(true);
});
it("should have App.Directives as a dependency", function() {
expect(hasModule('App.Directives')).to.equal(true);
});
it("should have App.Filters as a dependency", function() {
expect(hasModule('App.Filters')).to.equal(true);
});
it("should have App.Routes as a dependency", function() {
expect(hasModule('App.Routes')).to.equal(true);
});
it("should have App.Services as a dependency", function() {
expect(hasModule('App.Services')).to.equal(true);
});
});
});
});