Search code examples
javascriptunit-testingfunctional-programmingramda.jsnyc

Nyc coverage is not working for me when using functional approach with e.g. ramda


So my code is this:

const handler = (event = { body: {} }) => {
  if (isEventEmpty(event)) {
    return Promise.resolve({})
  }
  const getPayload = R.compose(
    R.flatten,
    R.map(x => transformRecord(x)),
    R.pluck('Stuff'),
    R.path(['body'])
  )
  const processEvent = R.compose(
    toPromise,
    R.ifElse(isEventEmpty, R.always({}), getPayload)
  )
  return processEvent(event)
}

module.exports = { handler }

With if (isEventEmpty(event)) { coverage is 66.67% which is fine. But without that if coverage will be 0. Notice that I use R.ifElse composable from Ramda. All unit tests pass that's why I'm not showing them, but coverage report shows 0% Branches 0/1. With imperative if branch I have 2/3 in coverage report.

Does anyone have also experience NOT using if-else branching (or loops) when writing their code? Seems that nyc is only looking in if-else, for/while branches or I might be wrong.


Solution

  • I don't think code coverage isn't working, it is simply becoming less useful in a functional programming setting.

    This is what I've shared in a presentation at work:

    Given yes-no.js:

    module.exports = bool => bool === true ? 'yes' : 'no';
    

    And yes-no-fp.js

    const {ifElse, equals, always} = require('ramda');
    
    module.exports = ifElse(equals(true),always('yes'),always('no'));
    

    And the following tests:

    test.true(yesOrNo(true) === 'yes');
    test.true(yesOrNoFp(true) === 'yes');
    

    Then you get the following code coverage:

    enter image description here

    As you can see for the same test:

    1. The functional programming version reports 100% branch coverage
    2. The "imperative" version reports 50% branch coverage

    Personally I think this is a good thing as I always say this to my team mates: code coverage is a tool not a rule. It should help you devise fewer but better tests. It should never be an aim.

    If 100% code coverage is your aim then there is a chance that nobody in code review will flag that you're missing a test case. Why should they if you have successfully covered the entire code?


    So how do you write better tests?

    I'm not sure there's a single answer to that question but I'd definitely recommend that you look into property-based testing. It can help you write more thorough tests for sure.

    If you're interested I found this article extremely useful.