-
Notifications
You must be signed in to change notification settings - Fork 787
Add some user flexibility for branch coverage stats #15
Comments
Number 1 is great, and I love 2. http://davglass.github.com/grover/lib/index.js.html Lines 26 & 27 are a perfect candidate for this! For 3 & 4, I think an |
For 1: I would recommend we not special case hasOwnProperty - as in hardcode that into istanbul behavior if that's what you meant by "automatically". It's a pretty wide-spread use case for lower branch numbers, which we probably don't want to test explicitly as we discussed - I'm not debating that. I just think hardcoding it in would be making assumptions about the code, which we can't reliably [100%] do. End users can just address that use case with solution 2 as a first step. I think the value there is that it's a conscious call being made by the owner of the code. From there we can see if we want to expose a flag [ ala jslint ] which says "ignore hasOwnProperty" - since it is a common use case - but still make it an explicit end-user choice [ opt in or opt out - either way ]. For 3/4: I think this is what Dav is saying too, but just a separate metric is sufficient as a first step. I think the main thing we're trying to protect against is the 'ignore branch' feature being used too casually/excessively/egregiously (or some other fancier word) - which just the additional metric/column seems to do. line % | statements % | branches % (after consciously ignored) | real branches % |
I think the comment configs are a great idea. We could potentially go the route of jshint and have enforcing options as well as relaxing options. We could potentially set the |
To me having a comment as to why the developer chose to ignore a specific branch for coverage is somewhat important since the initial reasons may not make sense when the code is refactored, for example. Maybe it is not as important for these comments to show up in the report. We could simply allow for additional comments/ reason in the same comment block without requiring them so the maintainer of the code can have some context as to the reasons of the original developer. |
I agree - capturing why the developer chose to ignore the branch is valuable/important for maintenance. I was just talking about the importance/priority of what to report really. |
Has anyone made progress on this? We had been using another tool in the past that supports marking blocks as covered and I am really missing this capability. |
no, not yet. |
To me another thing to add to this list is that no-op functions are currently required to be covered, e.g. var defaults = {
callback: function () {}
}; Currently requires you to cover the dummy function. Of course I suppose it might serve some purpose to cover a thing like this if you're out of meaningful tasks... :) |
The question is: why would you write a function that is never called? I mean: you cannot assume, in the general case that this sort of thing is incorrect behavior on istanbul's part. It is always possible to provide a strawman example for a specific case and say that the coverage tool has a problem. |
Finally found some time to work on this issue. Note that the code should be treated as alpha quality. Would like to get your opinions on the interface and behavior @davglass @sdesai @jussi-kalliokoski @abierbaum @mfncooper @reid @ariya @mathiasbynens Code is on the ignore-coverage branch. https://github.com/gotwarlost/istanbul/tree/ignore-coverage Interface:
Computations are done as before even in the presence of these comments but the coverage numbers are adjusted at reporting time. The HTML report shows the ignored sections as grayed out. To quickly see what it looks like for the existing example:
Feedback appreciated! |
Well, this is interesting but not very usefull to us. We would like to exclude entire functions because they are completely stubbed during the tests but spies and mocks. //#JSCOVERAGE_IF false //#JSCOVERAGE_ENDIF So, is there any way to do this with istanbul? |
No, not yet. I'm on vacation for the next 3 weeks and will take a look when I get back. Thanks for trying it out. |
I have a use case for applying this at a global level. Some mechanisms that are used in JS are used purely for ES3/5 code whilst waiting for ES5/6 Examples are for (var k in o) {
if (object.hasOwnProperty(k)) {
var v = o[k]
...
}
} Which gets replaced with for (var v of o) {
...
} Another example is function update(file, object, callback) {
fs.readFile(file, function (err, content) {
if (err) {
return callback(err)
}
var newValue = extend(JSON.parse(content), object)
fs.writeFile(file, JSON.stringify(newValue), function (err) {
if (err) {
return callback(err)
}
callback(null, newValue)
})
})
} vs function* update(file, object) {
var content = yield fs.readFile.bind(null, file)
var newValue = extend(JSON.parse(content), object)
yield fs.writeFile.bind(null, file, JSON.stringify(newValue))
return newValue
} In both cases I want to globally say ignore
if (err) {
return callback(err)
} |
Are there any plans or possible timeframe to merge the ignore-coverage branch? |
Also curious about being able to add ignore's to if/else conditions etc. It's the OCD in me I'm sure =) I could have 100% but I have 90% because |
This is by design. |
@sshrefler - the code change on the branch is not completely baked. Need to work on it some more before it can be merged. |
FWIW, I replaced the namespace patterns in the project with _.defaults(window, {myNameSpace: {}});
_.defaults(window.myNameSpace, {myObject: {}}); Now that I've been thinking about it, patterns that inevitably cause branches are kinda bad and can be avoided, and for example adding some pre-processor instructions to work around them makes the result even more ugly so I personally no longer think that this is a very useful feature. :) |
Needed for code blocks like:
|
👍 this would be a nice thing to have in istanbul |
👍 I need this for testing UMD modules. (function (root, factory) {
'use strict';
if (typeof exports === 'object') {
// CommonJS
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals
root.module = factory();
}
}) |
+1 for ignoring UMD wrapper. |
OK, I'm going to get serious in implementing this. It is almost done on the This following is the spec. Would love to get some feedback from all the people who have commented on this issue. The interface
How it worksWhen some part of the JS is considered skipped, nothing actually happens in terms of changes to the instrumentation. Everything is calculated as though nothing was skipped - all that changes is that there is a Coverage reporting however takes the This design makes it possible to report on either of the coverage numbers ("raw" v/s "processed"), show a count of statements/ functions/ branches skipped etc. Some of this stuff still needs to be developed. ExamplesThe first thing I did was of course to annotate the istanbul source code for hard-to-test cases, See commit 3faf816 for details. |
Are there any future plans to implement a (cli) switch to ignore all missing else-branches? |
No. Why do you need this? |
I have code that has multiple if statements which have no corresponding else statements. I have been adding /* istanbul ignore else */ individually for all these if statements in order to ignore the corresponding missing else statements. Is there are way to ignore all the missing else statements with a single comment? |
The case @anobika mentioned would be a use case for this feature. |
Hi, marking with comment parts of code to ignore in test coverage would be super useful. In my scenario i'm having code 100% in typescript and so there are bits of code added from compiler which will not get into cover - for instance there is an if in --extend method added each time you are using inheritance in code and there is no way to test that. regards. |
+1 for adding a a cli switch to ignore all "missing" else branches |
@FlorianLoch @anobika @ashishdasnurkar Is there a reason you are not testing to make sure the code inside the function foo(bar) {
if(bar) {
baz();
}
} should have 2 tests: var bar = true;
foo(bar);
expect(baz).toHaveBeenCalled(); var bar = false;
foo(bar);
expect(baz).not.toHaveBeenCalled(); to protect against future changes like function foo(bar) {
baz();
} |
@deckar01 Perhaps I got you wrong but as I mentioned I do noz control the code that shall be instrumented so I see no way to pick up your suggestion without the former mentioned parse-walkAST-generate step which I definitely want to avoid due to various reasons. |
@FlorianLoch I would recommend something like https://github.com/douglasduteil/isparta if the code is generated. Completely ignoring missing else branches has a very good chance of giving you false coverage reports. |
@davglass @reid @mfncooper @sdesai
Starting this thread to see how we can improve branch coverage in Istanbul.
Assumption: Default processing is just about ok in the sense of generality and hitting the cases we care about. If not, let me know.
Based on conversations with some of you here are some desires:
if (object.hasOwnProperty('foo')) {}
style branches where the else path should be considered non-existent and istanbul should probably not even consider thisif
statement as a branch.Anyway, ideas welcome. Just keep this issue updated and we can circle back 3-4 weeks from now and decide what needs to be done. I'll also need to do some research on how comments are made available in the parse tree by esprima before we decide the final solution.
The text was updated successfully, but these errors were encountered: