istanbuljs / nyc

the Istanbul command line interface
https://istanbul.js.org/
ISC License
5.61k stars 360 forks source link

async function "branch not covered" #265

Closed spudly closed 8 years ago

spudly commented 8 years ago

Almost every time I write a function with async/await syntax, I have this problem:

image

The tooltop indicates that there is a "branch not covered," but I've made sure to cover every branch.

The same statistics are given when nyc generates the coverage results in the terminal, which leads me to believe the problem is in nyc and not in istanbul.

image

That number should be 100%, but it thinks there's an extra code branch that's not covered.

If I've missed something obvious, or if there's a workaround for this, please let me know.

bcoe commented 8 years ago

@spudly unfortunately our ability to cover ES6 syntax is slightly spotty, would love help debugging; I know that @novemberborn has dug into this a bit, and has gone so far as writing a pure-ES6 proof of concept.

spudly commented 8 years ago

I'd like to help debug but honestly I have no idea where to begin or what to look for. Is there some documentation somewhere that can point me in the right direction?

novemberborn commented 8 years ago

The same statistics are given when nyc generates the coverage results in the terminal, which leads me to believe the problem is in nyc and not in istanbul.

nyc just wraps istanbul. I assume you're transpiling your async usage to generators? Most likely when we get the coverage for the transpiled code we're unable to map it back to your original source. When that happens nyc has no choice but drop that coverage.

bcoe commented 8 years ago

@spudly we have some similar bugs logged here:

https://github.com/gotwarlost/istanbul/issues/626

In lieu of us swapping out the guts of nyc with a more ES6 aware library (something that @novemberborn is working on) it might be worthwhile to start digging into Istanbul a bit more, to see if some of these mapping issues can be patched. Ultimately, this will most likely require a better understanding of esprima as well (more so than I currently have).

bcoe commented 8 years ago

@spudly I tried to recreate this issue (see #266) and have actually been unable to:

screen shot 2016-06-04 at 12 12 50 pm

I'm closing this issue in favor of #266, could you submit a failing example against that branch and we can use that as a jumping off point.

bcoe commented 8 years ago

@spudly give this a spin:

https://github.com/bcoe/nyc#use-babel-plugin__coverage__-for-better-es6es7-support

we've released better support for ES6/ES7 coverage using the coverage instrumentation library.

spudly commented 8 years ago

Sorry for the long delay. Tried the new solution, but I can't get past this:

Error: /Users/ssorense/workspace/cms-packages/packages/cms-cli/src/utils/login.js: Expected type "Statement" with option {}
    at Object.t.(anonymous function) [as assertStatement] (/Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/babel-types/lib/index.js:361:13)
    at Emitter.Ep.explodeStatement (/Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/babel-plugin-transform-regenerator/lib/emit.js:338:5)
    at /Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/babel-plugin-transform-regenerator/lib/emit.js:544:18
    at Array.forEach (native)
    at /Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/babel-plugin-transform-regenerator/lib/emit.js:543:38
    at Array.forEach (native)
    at Emitter.<anonymous> (/Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/babel-plugin-transform-regenerator/lib/emit.js:539:27)
Error: non-zero error code
    at Error (native)
    at ChildProcess.<anonymous> (/Users/ssorense/workspace/cms-packages/packages/cms-cli/node_modules/pify-process/build/pifyProcess.js:12:19)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
Ewocker commented 6 years ago

Hi, This is still happening to the latest nyc version, is there a change ? Using "babel-plugin-istanbul": "^4.1.6" "nyc": "^11.8.0" "istanbul": "^1.1.0-alpha.1" or "0.4.5"

This has been really annoying to me.

egrivel commented 5 years ago

Hi,

We're still getting this issue with current versions of nyc, istanbul, etc. It looks like the transpiler is adding an unreachable case statement. The following source code:

_testAsync: async (caseId, context) => {
  let response;
  try {
    response = await ajax.get('this/is/my/API/call', {context});
    return response.body;
  } catch (error) {
    response.message = 'Failure getting API response';
  }
  return response;
}

gets transpiled into:

_testAsync: function () {
  var _testAsync2 = _asyncToGenerator(
  /*#__PURE__*/
  regeneratorRuntime.mark(function _callee2(caseId, context) {
    var response;
    return regeneratorRuntime.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            _context2.prev = 0;
            _context2.next = 3;
            return dcps_ui_ajax__WEBPACK_IMPORTED_MODULE_1___default.a.get('this/is/my/API/call', 
              context: context
            });

          case 3:
            response = _context2.sent;
            return _context2.abrupt("return", response.body);

          case 7:
            _context2.prev = 7;
            _context2.t0 = _context2["catch"](0);
            response.message = 'Failure getting API response';

          case 10:
            return _context2.abrupt("return", response);

          case 11:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2, this, [[0, 7]]);
  }));

  function _testAsync(_x5, _x6) {
    return _testAsync2.apply(this, arguments);
  }

  return _testAsync;
}(),

and then it seems that case 11: is unreachable.

The same problem happens when the return response is inside the catch block, or when we throw an exception while handling the error.

elbertcastaneda commented 5 years ago

I have this problem with the last version of nyc (14.1.1):

async init() {
    super._emit('beforeInit');

    await this.setForeignKeys(async () => {      // <<-- This async statement is the problem (My coverage report showed "Branch not covered" in this line)  
      const foreignKeys = await this._getForeignKeys();
      return foreignKeys;
    });
}
Screen Shot 2019-07-10 at 9 43 23 PM

I'm going to add my devDependencies in case they would be helpful for something:

{
"...": "...",
"devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/plugin-proposal-class-properties": "^7.4.4",
    "@babel/plugin-proposal-export-default-from": "^7.2.0",
    "@babel/plugin-transform-runtime": "^7.4.4",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.4.5",
    "@babel/register": "^7.4.4",
    "@babel/runtime": "^7.4.5",
    "@types/knex": "^0.16.1",
    "babel-eslint": "^10.0.2",
    "chai": "^4.2.0",
    "eslint": "^6.0.1",
    "eslint-config-airbnb-base": "^13.2.0",
    "mocha": "^6.1.4",
    "nodemon": "^1.19.1",
    "nyc": "^14.1.1",
    "sinon": "^7.3.2",
    "source-map-support": "^0.5.12"
  },
"...": "..."
}
coreyfarrell commented 5 years ago

Please open a new ticket including all required information (especially a minimal demonstration repository). No action will be taken on this ticket.

shonubijerry commented 5 years ago

I noticed that when I declare a method inside a class namespace using async/await, nyc will cover all its branches but, if I declare the same method with async/await outside a class namespace, nyc will report branch not covered in its coverage.

edmooliveira29 commented 2 years ago

I solved only updating version of the node to 15.12.0