Istanbul: Odd branch coverage issues with generator functions

Created on 14 Jun 2016  Â·  8Comments  Â·  Source: gotwarlost/istanbul

Hi there! So I've been using istanbul for code coverage. Big fan. The project I've been using it on is a React/Redux app that utilizes Redux-Sagas. The big thing with sagas is it's use of generator functions. I've found that there's some ... weird branch-coverage issues when it comes to branch coverage. I've attached a couple screenshots to demonstrate.

screen shot 2016-06-13 at 8 47 37 pm

screen shot 2016-06-13 at 8 44 33 pm

screen shot 2016-06-13 at 8 44 42 pm

Not really sure what's going on with this. I'm not too concerned, as I know I've covered the code. Would just be nice to see those 100% across the board

Most helpful comment

I was confused by the happy result with no real solution other than pointing the finger at Babel.

I, too, was having this issue with a project I am working on with React/Redux/Sagas. This post sent me looking for a way to skip the coverage on the 'extraneous' if just to find out that both Babel and Istanbul were correctly reporting coverage from my tests.

Poking with a stick, /* istanbul ignore if */, didn't seem to help other than making me think harder. I read this article on generators.

given:

    function* dataConsumer() {
        console.log('Started');
        console.log(`1. ${yield}`); // (A)
        console.log(`2. ${yield}`);
        return 'result';
    }

behavior:

    > let genObj = dataConsumer();
    > genObj.next()
    Started
    { value: undefined, done: false }

    > genObj.next('a')
    1. a
    { value: undefined, done: false }

    > genObj.next('b')
    2. b
    { value: 'result', done: true }

The underlying result is a branch condition indicating exit with the done property equal to true. The missing test, in my case, was to call the final next and receive an object with done: true
(This can be extra troublesome in the cases where working with Sagas you might have a sequence of events wrapped in a while(true) statement. (Following examples from the interwebs doesn't always give you testable code ;-) ))

Hope this is helpful

All 8 comments

Is there a workaround possible with /* istanbul ignore XX */? I tried if because in the HTML report is shows this 'I' symbol, but nothing changes. When I use next the whole function is ignored :(

2016-06-15-184045_759x545_scrot

I presume you are transpiling this code? I _think_ what is going on is that the transpiler is putting in a conditional in front of the generator function causing the ignored branch.

Right, I use Babel.

Krishnan Anantheswaran [email protected] schrieb am So., 19. Juni
2016 19:31:

I presume you are transpiling this code? I _think_ what is going on is
that the transpiler is putting in a conditional in front of the generator
function causing the ignored branch.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/gotwarlost/istanbul/issues/645#issuecomment-227009619,
or mute the thread
https://github.com/notifications/unsubscribe/AAJ9OD9r4WWrcahhqlk0JG5UZtY8VBP4ks5qNXzrgaJpZM4I03dM
.

:+1:

I was confused by the happy result with no real solution other than pointing the finger at Babel.

I, too, was having this issue with a project I am working on with React/Redux/Sagas. This post sent me looking for a way to skip the coverage on the 'extraneous' if just to find out that both Babel and Istanbul were correctly reporting coverage from my tests.

Poking with a stick, /* istanbul ignore if */, didn't seem to help other than making me think harder. I read this article on generators.

given:

    function* dataConsumer() {
        console.log('Started');
        console.log(`1. ${yield}`); // (A)
        console.log(`2. ${yield}`);
        return 'result';
    }

behavior:

    > let genObj = dataConsumer();
    > genObj.next()
    Started
    { value: undefined, done: false }

    > genObj.next('a')
    1. a
    { value: undefined, done: false }

    > genObj.next('b')
    2. b
    { value: 'result', done: true }

The underlying result is a branch condition indicating exit with the done property equal to true. The missing test, in my case, was to call the final next and receive an object with done: true
(This can be extra troublesome in the cases where working with Sagas you might have a sequence of events wrapped in a while(true) statement. (Following examples from the interwebs doesn't always give you testable code ;-) ))

Hope this is helpful

Is there any update to this issue?

@gdw-atwork nice catch man! You saved my life :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

graemej picture graemej  Â·  22Comments

blindenvy picture blindenvy  Â·  19Comments

niftylettuce picture niftylettuce  Â·  29Comments

schulzch picture schulzch  Â·  151Comments

jonathanong picture jonathanong  Â·  18Comments