Hi there,
my goal is to improve karma to not always run the whole test suite when a file changes.
To avoid lots of effort going in the wrong direction I would like to talk about this first, before starting the implementation.
Improve karma to not always run the whole test suite when a file changes
This is an important issue in larger projects with a lot of tests. Changing a file (using autoWatch or grunt-karma) usually triggers a run of the whole test suite. This is not always necessary and can be avoided.
There are two isolated sets of files that usually trigger a re-run of all the tests:
Regarding the first category one cannot do much easily. What one can do, is to derive the set of spec files four each source file from the first test run (maybe Istanbul can help here?). This is not what my proposal is about (although it should be done, but not as a first step).
What I want to improve is the second set of files: when changing a spec file, karma should run only this particular spec file
So let's talk about the ...
Improve karma to not run the whole test suite when only a spec file changes
isspec and defaulting to false. If set to true for file _A_, karma could (when the watcher detects a change in _A_) load (i.e. include as in the _included_ setting) only those files who have isspec == false plus _A_. Conversely, if the watcher detects a change in file _B_ which we assume to have isspec == false, then it would just load the files as usual.** The ideal setup I would like to support involves using (1) grunt-watch, setting up two different watch-targets, one for watching the source files and one for watching the spec files, and using (2) grunt-newer for the spec-files watch task to be able to dynamically pass only the changed files to the _grunt-files array_, e.g. like so: 'newer:karma:run'. Respecting the _grunt-files array_ was only "recently" (in January) made possible.
What do you think? If anything is unclear, I'm happy to try and explain more thoroughly.
I'm feeling that especially change No. 2 could be solved differently in many ways (e.g. letting grunt-karma do more of the work, like WebStorm does, for which the changes in runner.js were introduced in the first place, i.e. the changes to allow for notification on added/removed/changed files).
Regards,
Nicolas
Assuming this is meant in the context of someone working on the specific Spec file isn't the feature not already available via focused specs ( http://jasmine.github.io/2.3/focused_specs.html ) ?
Edit: I just realized that maybe you are not using jasmine... ignore my answer if that's the case.
Hey, first of all thanks for the extensive proposal. In regards to the second point you are suggesting, have you looked at #1468 ? As it seems to me this could potentially solve the issues you are mentioning here, or at least make things easier to handle.
In terms of actually running only specific spec files I think the idea of telling karma explicitly about this does make sense, but adding it as another option might make the api very complicated. Maybe we could split the files config into two parts like this:
files: {
library: [
'lib/**/*.js'
],
tests: [
'test/**/*.spec.js'
]
}
@fbengrid: I'm well aware of this option, but as you've said, it is only available when using jasmine (and even there it's more of a hack: the angular team even wrote its own grunt task to ensure that no ddescribe or iit methods are accidentally committed ...)
@Dignifiedquire
Concerning extracting the watcher, I've just replied in that thread: https://github.com/karma-runner/karma/issues/1468#issuecomment-125212286
Regarding the files config. My first approach was similiar to your suggestion (adding a sibling config option like filesSpecs). But then I thought: isn't it easier to just setup the files array as usual? Using your suggestion, one would have to (1) write/support/maintain code that works both ways, while (2) maintaining the docs accordingly (either telling that both ways were supported, or introducing what looks like a breaking change in the docs (i.e. people coming from an old karma config file would think that their config was no longer valid).
To mitigate (1) one could deprecate the current usage sometime in the future. Which goes against backwards compatibility ...
Maybe it helps if we look at this change from the perspective of a small set of users (let's call them _crazy optimizers_) that try to optimize their dev environments as much as possible. Until now, developers have lived with their test suites running as a whole on every change ... so maybe they won't be missing much if this new setting was somehow "hidden" inside the files pattern object. The _crazy optimizers_ however will eventually find out about this option and be very happy. After all, not every project really needs this improvement, if they have only a small test suite ...
I agree, adding it as yet another option to the files pattern object makes it seem more complicated ("yet another possible option, very nested, very hidden"). This is justified, however by these arguments:
files like it is todayincluded: false, served: true correctly) sometimes one wants to serve other resources via karma, too (like images, css, ...).@NicBright thanks for all the detailed work, I haven't forgotten you, just hadn't the time to go through it in detail.
Protractor does this by specifying suites{} in the config file and then running a particular suite from the command line like 'Protractor --suite moduleX'.
I think it would be great for Karma to work the same way, it's easy to set up and run. But this is missing from Karma.
@stuartaylward Your proposal does not really fit into this topic. This topic is about making karma itself smarter. Regarding your proposal: Karma in my understanding is "just" a test runner. It runs the tests you say it should run. So you can just use different karma config files (or different grunt tasks). One for each logical suit.
I have the same problem for my new project which is based on angularJs.
I have been solved this with my solution that I think would be useful to write it here.
My project directory structure is as follow:
โ_ admin
โ โโ dashboard
โ โ dashboard.module.js
โ โ dashboard.component.js
โ โ dashboard.specs.js
โ โโ search
โ โ_ register
โ
โโ user
โโ node_modules
โ karma.conf.js
โ webpack.config.js
โ ...
...
...
karma.conf.js
module.exports = function(config) {
/**
* Env or Command Line arguments to find the `specs` for test
* Example: npm run admin:register start just register component tests
* Example: npm run admin starts all admin components tests
*/
config.set({
files: [ /* test files */ ],
preprocessors: {
'*specs.js': [ 'webpack' ]
}
})
}
I'm also interested in the idea that @NicBright has presented here. Why hasn't there been any progress on this?
This would be a really interesting change. I've come here looking for an alternative to wallaby.js which is built entirely on this premise (quite successfully). If Karma were able to do this out the box (and even extend it in the future to run just impacted tests based on code coverage) it'd be a big step forward for TDD.
+1
Related SO questions with workarounds using Gulp/Grunt to control Karma:
+1
+1
I also first commented with "+1" but then I learned that this will spam all persons that already wrote a comment.
=> Please use the thumbs up feature on the issue description.
+1
+1
+1
A property that lets us use a custom function to determine which file(s) to run tests on would be ideal, if it couldn't be easily automated.
For example:
**/*.spec.* file is the 'changed' file for the event. We detect that spec is part of the filename in our custom function and trigger tests to be performed for this file. Just need the karma runner to accept a specific file name.
And if we change another file, we could use the custom function to determine all related tests, or just run all of them if the spec file isn't what was updated. Etc etc etc.
Ultimately, I just need a way to trigger a test on a specific file or files once the karma server is running...
Most helpful comment
I also first commented with "+1" but then I learned that this will spam all persons that already wrote a comment.
=> Please use the thumbs up feature on the issue description.