swc: Incorrect Jest coverage
When using @swc/jest to transpile ts to commonjs and running jest --coverage
certain branches are shown as not covered (console logging in these branches show that tests do run the code path). Using babel to transpile and run the tests shows the correct coverage.
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 51
- Comments: 68 (17 by maintainers)
Commits related to this issue
- swc/jest is not reporting coverage correctly https://github.com/swc-project/jest/issues/21 — committed to FreakinWard/nextjs-boilerplate by FreakinWard 3 years ago
- Next v12 upgrade (#34) * upgrade to next v12 * removed babel for swc * npm updates including msw and lint * azure pipeline now builds with node v16 * swc/jest is not reporting coverage correctl... — committed to FreakinWard/nextjs-boilerplate by FreakinWard 3 years ago
- build(all): fix test setup - remove babel - usw swc transform - fix wallaby config - remove coverage thresholds due to https://github.com/swc-project/swc/issues/3854 - generate coverage report as PR ... — committed to feature-hub/feature-hub by unstubbable 5 months ago
- build(all): fix test setup - remove babel - usw swc transform - fix wallaby config - remove coverage thresholds due to https://github.com/swc-project/swc/issues/3854 - generate coverage report as PR ... — committed to feature-hub/feature-hub by unstubbable 5 months ago
- build(all): fix test setup - remove babel - usw swc transform - fix wallaby config - remove coverage thresholds due to https://github.com/swc-project/swc/issues/3854 - generate coverage report as PR ... — committed to feature-hub/feature-hub by unstubbable 5 months ago
I added this to my Jest configuration in
package.json
which seemed to help.@kdy1 Hm, I tested both
sourceMaps
in.swcrc
and as an option in thejest.config.json
. Both did not work for me. Even withtarget: "es2021"
.For my NestJS project, I also noticed that test coverage dropped quite a bit when switching from
ts-jest
to@swc/jest
.Digging into it, it seems to be related to how the Typescript metadata for constructors are transpiled.
Take this constructor:
The output of
swc
for thedesign:paramtypes
metadata for the constructor is:Notice the
typeof
ternary. This gets flagged as an “uncovered branch” by istanbul, the coverage calculator used by jest.Compare this to how
ts-jest
outputs this:No ternary, so no impact to code coverage.
I created a workaround that tells istanbul to ignore these lines that incorrectly impact code coverage. It inserts an
/* istanbul ignore next */
comment in the necessary places, resulting in transpiled code like this:I setup this repo with instructions to reproduce: https://github.com/rogisolorzano/nest-swc-coverage
The workaround I’m using is in create-swc-transformer.js
Curious if there are any thoughts on this and potential solutions that don’t involve having to insert
/* istanbul ignore next */
into the transpiled output byswc
?I think https://github.com/swc-project/swc/pull/7900 may improve the situation.
@pspeter3 Thank you for your code snippet, it helps, but now there is another problem:
It looks like not covered code highlights are not displayed correctly.
There is an example of coverage report from project with:
jest@27.3.1
@swc/core@1.2.118
@swc/jest@0.2.11
the yellow highlight here says that the comma is supposedly not covered
@krutoo ran into the same issues and guessed it is caused by the conversion to older JS syntax. We could fix these false-positives by targeting a newer ES version.
Our issue was that components that were using emotion were being tested but not captured in the coverage reporting. Using
sourceMaps: 'inline'
was all it took to get coverage back up to where it was.I saw mention of using
@swc-node/jest
vs@swc/jest
what are the differences?I’m using NestJS as well and this seems to be related to decorators, so removing the
legacyDecorator
and/ordecoratorMetadata
is not an approach I can test.This seems to be very related to an issue
ts-jest
was/is having here, maybe there’s some insight to be taken from there? If they did resolve it I think it was via a similar method as rogisolorzano provided which is adding istanbul ignore comments.I think I’ve tried all configuration permutations listed here so far without any luck, as well as installing
@swc-node/jest
&@swc/helpers
and trying it as the jest transformer. One thing to note to keep you sane is that you may need to runnpx jest --clearCache
between configuration changes it seems before running your next jest coverage run (I noticed removing the transform decorators in my swcrc config broke tests, and still showed they were broken after reverting everything ?!).Potentially Related Issues on Other Projects
Ultimately it sounds like source mapping can help some scenarios, changing the target in other scenarios, but specific decorators don’t seem to care about either of those in some scenarios like Angular and NestJS commonly it seems.
I took some time to checkout the related “fix for decorator coverage” that I linked above. It does seem they took the same approach as @rogisolorzano 👍
I’m not sure if this project has a way to implement a “pre-processor” but maybe that’s something @rogisolorzano could open a PR for is this is how folks seem to be getting around this. Otherwise it sounds like there needs to be a major rework on the system to implement so that it doesn’t require a ternary (or is this an underlying transpilation implementation issue of these frameworks with how the decorator is written?).
https://github.com/kulshekhar/ts-jest/pull/488/files#diff-0548fd42c45d69a916cd9689c388d2c60b74746b4b7626a008167273557b4e57
PS: Thanks @rogisolorzano for the minimal reproduction and digging deep into this.
@klutzer are you not using Jest? I believe that’s the scope of this issue, but I believe the coverage issue is not directly related to jest but the coverage tool [istanbul].
I had the same issue. But when I changed
sourceMaps: true
tosourceMaps: "inline"
, jest started to collect coverage correctly.My config is:
Ofc, Adding the option to
.swcrc
works as well.Hope this helps people.
@kdy1 Here it is: https://github.com/sarneeh/swc-project-swc-issues-3854
When I was creating it I noticed that the false-positives go away when I turn off
decoratorMetadata
option (which is unfortunately required when using dependency injection frameworks like typedi). Hopefully that will help you somehow 🙏Also found that unused exports are marked as uncovered statements:
Removing
export
makes them covered.I tried:
externalHelpers: true
decorators: false
target: "es2021"
sourceMaps: true
Unfortunately, it does not help to restore the coverage and even also makes it worse.
Useing
coverageProvider: 'v8'
will probably solve the problem. Solution funded at stackoverflow https://stackoverflow.com/a/74851858/8770040I’ve tested with
"sourceMaps": "inline"
but didn’t work..swcrc:
package.json:
I’ve noticed that jest coverage will report code branches inside helper functions as being uncovered lines unless the
externalHelpers:true
options is specified.Adding this option improved my test coverage significantly since the helper code is no longer included in the coverage scan. I’m not sure if anyone else has encountered this?
I opened a PR to add this option in
@swc-node/jest
but it probably needs further investigation/discussion https://github.com/swc-project/swc-node/pull/673The clue about
decoratorMetadata
really helps! I already fixed codegen and it means some transform is dropping source map information, and now I know which pass is doing so. Thank you!yes, can confirm. This is still not fixed. But
/* istanbul ignore next */
now works 😃You need
sourceMaps: true
orsourceMaps: "inline"
. I verified that it’s workingMy specific problem seems to have been resolved by https://github.com/swc-project/swc-node/pull/673, for what it’s worth.
This is true… 😐
Sure. @960590968 Here are my config files for testing. And I’m using React. Basically,
swcConfig
is configs from.swcrc
jest.config.js
jest.setup.js
.swcrc
Dependencies
// package.json
Yes, it will definitely help. Ideally if I can invoke jest to get coverage for single file, I can test/ensure that jest reports 100% coverage
Hey @kdy1 my reported issue here is now fixed for me with
"@swc/jest": "0.2.22"
@sebald Thank you, looks like it realy works with
target: "es2021"