Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support istanbul coverage provider #1676

Merged
merged 35 commits into from Aug 15, 2022

Conversation

AriPerkkio
Copy link
Member

@AriPerkkio AriPerkkio commented Jul 19, 2022

Closes #1252

Documentation of the istanbul packages is not perfect. I had to do some analyzing of jest and nyc to get things working.

Creates common interface for coverage providers to implement and adds new coverage provider:

  • onFileTransform:

    • c8: No file transforms needed
    • istanbul: Instrument files under testing with istanbul-lib-instrument. Coverage objects are added to globalThis.__VITEST_COVERAGE__
  • onBeforeFilesRun:

    • c8: Instruct v8 to enable coverage collection by setting up process.env.NODE_V8_COVERAGE
    • istanbul: No actions needed
  • onAfterSuiteRun:

    • c8: Write v8 coverage reports to file system using v8.takeCoverage()
    • istanbul: Collect the globalThis.__VITEST_COVERAGE__ from workers through birpc into main thread
  • onAfterAllFilesRun:

    • c8: Create report using c8/lib/report
    • istanbul: Process and merge coverage objects with istanbul-lib-coverage and create report with istanbul-reports

Example

vitest/test/coverage-test/src/utils.ts: Istanbul on the left with 57% coverage, v8 on the right with 70% coverage:

image

@AriPerkkio
Copy link
Member Author

This is still a work-in-progress but it might be worth to create a draft PR at this point to prevent duplicate work.

I think the refactor: create interface for coverage logic part is complete, but istanbul integration still requires work. I can continue this later on, but if anyone is eager to finish this PR let me know.

I think it's also good time for Vitest team to take a look at this overall and call for a stop if this doesn't look good.

packages/vitest/src/node/core.ts Outdated Show resolved Hide resolved
packages/vitest/src/node/plugins/index.ts Outdated Show resolved Hide resolved
packages/vitest/src/runtime/run.ts Outdated Show resolved Hide resolved
Comment on lines 38 to 48
// TODO: Requring all these packages to be installed by users may be too much
const requiredPackages = ctx.config.coverage.provider === 'istanbul'
? [
'istanbul-lib-coverage',
'istanbul-lib-instrument',
'istanbul-lib-report',
'istanbul-reports',
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can create @vitest/istanbul package that just reexports what is needed.

@vitest-dev/team What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it sounds great to me
#1676 (comment)

@AriPerkkio AriPerkkio force-pushed the feat/coverage-provider-istanbul branch 2 times, most recently from bc73f74 to 36b3f17 Compare July 21, 2022 07:27
@AriPerkkio AriPerkkio force-pushed the feat/coverage-provider-istanbul branch 3 times, most recently from e657060 to 5b48782 Compare July 22, 2022 11:43
@AriPerkkio AriPerkkio force-pushed the feat/coverage-provider-istanbul branch 3 times, most recently from fea9cce to fc13750 Compare July 23, 2022 11:14
this.ctx = ctx
this.options = resolveIstanbulOptions(ctx.config.coverage, ctx.config.root)

const { createInstrumenter } = require('istanbul-lib-instrument')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be cool to see this configurable to use custom instrumenters like https://github.com/kwonoj/swc-coverage-instrument/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a cool idea, thanks for improvement idea @wight554. However I think it might be best if we leave this customization out of this PR and introduce it in a separate feature afterwards.
Do you think there is anything important we need to take into consideration at this point? Leave some abstractions in place, etc?
My Rust knowledge is a bit rusty and to me it's not that clear what exactly import('swc-plugin-coverage-instrument') would return here. Does it match the API of istanbul-lib-instrument?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a cool idea, thanks for improvement idea @wight554. However I think it might be best if we leave this customization out of this PR and introduce it in a separate feature afterwards. Do you think there is anything important we need to take into consideration at this point? Leave some abstractions in place, etc? My Rust knowledge is a bit rusty and to me it's not that clear what exactly import('swc-plugin-coverage-instrument') would return here. Does it match the API of istanbul-lib-instrument?

I've checked how jest handles this, see https://github.com/facebook/jest/blob/24e0472ac41ea03cdd89ffaea8c5f410ecf6054f/packages/jest-transform/src/ScriptTransformer.ts#L410
In this case all that needs to be added is config value to skip instrumenter part and return unmodified map and code in onFileTransform

@wight554
Copy link

wight554 commented Jul 26, 2022

looks good overall, noticed few issues:

  1. exclude option seems to be ignored when using instanbul
  2. when setting provider to c8 explicitly vitest run --coverage skips coverage
  3. vitest doesn't suggest installing missing istanbul packages and skips coverage instead
  4. c8 randomly ignores coverage for 1 file in 100% covered code when using c8 with these changes

codebase I used for testing: https://github.com/wight554/blog-template
You might notice schemas are added to coverage report when using istanbul [1] if you try

Upd. I use typescript instead of esbuild for compiling tests but ts-jest does the same and uses default jest instrument, so shouldn't be an issue
Upd2. if matters:

  System:
    OS: Windows 10 10.0.22622
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 17.38 GB / 31.93 GB
  Binaries:
    Node: 16.14.0 - c:\program files\nodejs\node.EXE
    Yarn: 3.1.1 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 8.3.1 - c:\program files\nodejs\npm.CMD
  Browsers:
    Chrome: 103.0.5060.134
    Edge: Spartan (44.22621.436.0), Chromium (103.0.1264.71)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    vite: ^3.0.3 => 3.0.3
    vitest: 0.19.1 => 0.19.1

@antfu
Copy link
Member

antfu commented Jul 26, 2022

The overall direction looks great to me. Please ping me when you think the work on your side is done, and I can help to do the refactoring and make the packages more general as @vitest/coverage-istanbul and even @vitest/coverage-c8 later.

@AriPerkkio
Copy link
Member Author

AriPerkkio commented Jul 26, 2022

From my side all that is left to do is unit+manual testing and add documentation. I think everything else (besides refactoring into separate packages) is done. I'm happy to leave these tasks to other people as well. 😄

I'm currently travelling and won't be doing anything for the next ~10 days. @antfu if you'd like to start working on this now, feel free to take over the PR. 👍

@antfu
Copy link
Member

antfu commented Jul 26, 2022

Great, thanks! Have a good time traveling!

@AriPerkkio AriPerkkio force-pushed the feat/coverage-provider-istanbul branch 2 times, most recently from 1bfd7e0 to 15d1ddc Compare August 2, 2022 15:30
@AriPerkkio AriPerkkio force-pushed the feat/coverage-provider-istanbul branch 3 times, most recently from 4c060d9 to 0d28eb2 Compare August 4, 2022 18:26
@AriPerkkio
Copy link
Member Author

There's now some initial documentation and unit tests in place. I think the next logical step is to refactor these coverage providers into their own packages - #1676 (comment).

@sheremet-va
Copy link
Member

There's now some initial documentation and unit tests in place. I think the next logical step is to refactor these coverage providers into their own packages - #1676 (comment).

I think we should have these packages:

  • @vitest/coverage-v8
  • @vitest/coverage-istanbul

Then Vitest checks for coverage field, if package is installed. We might also expose this as CoverageProvider for extending with custom provider.

@antfu antfu marked this pull request as ready for review August 15, 2022 06:09
@antfu antfu requested a review from Demivan August 15, 2022 09:32
@Demivan
Copy link
Member

Demivan commented Aug 15, 2022

@antfu coverage-c8 and coverage-istanbul build is failing locally.

src/provider.ts(6,10): error TS2305: Module '"vitest/config"' has no exported member 'configDefaults'.

@Demivan
Copy link
Member

Demivan commented Aug 15, 2022

@antfu antfu enabled auto-merge (squash) August 15, 2022 18:19
@antfu antfu disabled auto-merge August 15, 2022 18:20
@antfu antfu merged commit 265fdbe into vitest-dev:main Aug 15, 2022
@AriPerkkio AriPerkkio deleted the feat/coverage-provider-istanbul branch August 15, 2022 18:40
@JounQin
Copy link

JounQin commented Aug 17, 2022

It should be noticed provider: 'istanbul' is required if the user wants to use istanbul, ideally, if @vitest/coverage-istanbul is detected, istanbul should be used by default IMO.

@antfu
Copy link
Member

antfu commented Aug 18, 2022

I thought about it as once, but it could be complex to handle, like if you have both c8 and Istanbul packages installed, or if we have more providers in the future. Also, it might be dangerous to have dependencies change the behavior implicitly.

@JounQin
Copy link

JounQin commented Aug 18, 2022

@antfu

But the current behavior is very strange.

When provide: 'Istanbul' is not enabled but @vitest/coverage-istanbul installed

 MISSING DEP  Can not find dependency '@vitest/coverage-c8'

✖ Do you want to install @vitest/coverage-c8? … no

There is no choice or notice to add provide: 'Istanbul'.

When provide: 'Istanbul' enabled with @vitest/coverage-istanbul installed

Coverage enabled with istanbul

This message is very redundant to appear every time.

if you have both c8 and Istanbul packages installed, or if we have more providers in the future

IMO, something like Coverage enabled with istanbul is just for this case, for the default fallback or conflict providers installed message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Coverage: give the choice between c8 and nyc
6 participants