adana-coverage / babel-plugin-transform-adana

Like Istanbul but for babel.
11 stars 4 forks source link

Coverage and line counting issues. #39

Open olegskl opened 8 years ago

olegskl commented 8 years ago

I'm continuing working on the HTML reporter and starting to get visual representation of our code coverage. There are some issues, mostly due to the fact that the lines function in adana-analyze reports all lines between loc.start and loc.end as covered with coverage count of the parent node. This not only results in empty lines having coverage count, but also in the fact that empty lines have higher count than their neighboring lines with statements and the such (compare lines 18 and 19).

original

So, I changed the line counting loop to only include loc.start and use Math.max on counts. This solves two issues:

  1. The lines reported as covered are actually covered.
  2. Lines with function assignments actually show the count of function declaration, not the count of function executions. Same goes for a single line ternary expressions. If the falsy branch of a ternary is not covered, that doesn't mean that the ternary is not executed at all.

Below is the screenshot of the result. It's only a little bit better.

  1. I don't know what to do with functions. On one hand I think it's good that we're tracking the execution count for the "function" tag, but the visual representation is weird (see line 2).
  2. Method calls don't seem to be covered.
  3. Something wonky is going on with conditionals (see lines 11 and 13).
start-loc-only
izaakschroeder commented 8 years ago

Thanks for highlighting all this! I have struggled with the lines algorithm myself still in determining what actually makes the most sense for some of these cases. I'll see if I can review this later tonight and maybe we can come up with some rules.

You may find it handy to include a list of locations hit in your metrics for lines (e.g. line 4 hit locations 5 and 7) – that will give you insight into some of the "magic". My guess for the magic is that adana is injecting and counting its phantom "else" branch there and both are being counted for that line. I don't know that for sure, but that's my guess.

I'm not sure what to do about certain expressions – I feel like an expression statement (in general) should cover all lines in that statement (e.g. in yours the line 19 statement should cascade through to line 32). I don't know if I want to add coverage for every single operator? Maybe? It could be done certainly (and at present there is no markers added for operators of any kind). It would enhance the accuracy of statements like:

const x = 
  foo() +
  bar() + // if this line throws an error then baz won't be covered 
  baz();

Also you should totally move your html formatter repo over to the org if you'd like! I'll delete the shell one I have and yours can replace it. :smile:

olegskl commented 8 years ago

I had never written a babel plugin before, so in order to learn I started a rewrite of adana transformer from scratch and came up with a version that seems to work well for the app we're working on here.

Below is a screenshot of the code coverage with my version of adana. It's quite similar to the report that we get from Istanbul, but the big plus is that the branch count is better (Istanbul reports 20 branches because it is based on the transpiled results).

adana-rewrite-file1

I'm also adding an example that has classes, super and destructuring:

adana-rewrite-file2

I'll clean up the code and upload it so that you can take a look.

olegskl commented 8 years ago

Here it is: babel-plugin-transform-adana-alt. I really should have done it as a fork, but at the time I thought I was just going to play around... I will prettify it and make a proper MR if we decide to use it.

Notable changes:

Also there's Tape for unit tests, but I can switch to Mocha if you think it's better. And for linting I used eslint-config-meetic because we're actively using it in our projects (and frankly I'm not really a fan of metalab config, because it changes too much from one version to another, has a dependency on react plugin and v2 wants me to use function expressions for some reason).

And I really want to change the name "prelude.js" to something else... have no ideas yet.

izaakschroeder commented 8 years ago

Phew lot to go over :smile:

izaakschroeder commented 8 years ago

My recommendation is to (in priority order):

Additionally at some point (if you want):

Thanks again for all the hard work and interest in this!

izaakschroeder commented 8 years ago

Also as a total aside regarding tags: it might be interesting to write a function in adana-analyze that collects all the tags for a given line. In your HTML formatter you could then generate color codes for each tag. e.g. blue for statement, purple for branch and so on. For each line instead of a huge green bar you display colored stripes. You could desaturate an individual tag color on a line if the count is 0 for that tag. This would be a good segway into showing how user-defined tags can be used (basically a mechanism to group coverage information together) – you can visualize things like "show me all coverage dealing with compression" (which maybe in this case means you hide every other color or dim all lines without the "compression" tag). There a lots of possibilities! :tada:

olegskl commented 8 years ago

Thanks for explanations! I the user-defined tag idea is great. (Side note regarding tags: I've made a PR to adana-analyze because it threw an error when I attempted to instrument a class constructor).

There are some ideas for a more interesting highlighting of the code and functionality in the html reporter (like ranges and drill-down on click or mouseover), but there's just not enough time to do it all. I'll get to it eventually.

Let's stick to Mocha for the time being.