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

[FR]: Use jest-monocart-coverage with v8 and lcov instead of c8 #288

Open
Aghassi opened this issue Jul 9, 2024 · 0 comments
Open

[FR]: Use jest-monocart-coverage with v8 and lcov instead of c8 #288

Aghassi opened this issue Jul 9, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@Aghassi
Copy link

Aghassi commented Jul 9, 2024

What is the current behavior?

The current coverage reporters are not accurate enough and lead to bad line assignments and incorrect coverage values.

Describe the feature

The current coverage behavior is actually kind of buggy and I've spent a month debugging it so I figured I'd ask for this to be added. On our end, we've patched our way out of the coverage collection because it just doesn't do what we want and it has been cumbersome to get right.

How I fixed this on my end:

  1. I needed to add flags around
    let coverageFile = path.basename(process.env.COVERAGE_OUTPUT_FILE);
    let coverageDirectory = path.dirname(process.env.COVERAGE_OUTPUT_FILE);
    if (process.env.SPLIT_COVERAGE_POST_PROCESSING == "1") {
    // in split coverage post processing mode bazel assumes that the COVERAGE_OUTPUT_FILE
    // will be created by lcov_merger which runs as a separate action with everything in
    // COVERAGE_DIR provided as inputs. so we'll just create the final coverage at
    // `COVERAGE_DIR/coverage.dat` which then later moved by merger.sh to final location.
    coverageDirectory = process.env.COVERAGE_DIR;
    coverageFile = "coverage.dat";
    }
    config.coverageDirectory = coverageDirectory;
    config.coverageReporters = ["text", ["lcovonly", { file: coverageFile }]];
    that let's me eject from this so I can set these variables myself. That may not be necessary for this feature. The main thing is not to set coverageReporters if one is provided. I also removed
    config.collectCoverageFrom = readFileSync(process.env.COVERAGE_MANIFEST)
    .toString("utf8")
    .split("\n")
    .filter((f) => f != "")
    .map((f) => path.relative(jestConfigDir, f));
    }
    as it never worked right and messed up split coverage in our case.
  2. Set coverageReporters to coverageReporters: ['none'],
  3. Add the following to reporters
    [
     'jest-monocart-coverage',
      {
        name: 'Coverage Report',
        outputDir: `${process.env.COVERAGE_DIR}/jest_mcr_temp`,
        reports: [['v8'], ['lcovonly']],
        sourceFilter: '**/*.{ts,tsx}',
      },
    ],
  1. Create a globalTeardown script with the following
import fs from 'fs'
import path from 'path'

const outputDir = `${process.env.COVERAGE_DIR}/jest_mcr_temp`

export default async function globalTeardown() {
  // If bazel coverage is being run, otherwise don't do this
  if (process.env.COVERAGE_DIR) {
    /**
     * generate the lcov report by merging all the existing
     * lcov info files from the coverage dir generated
     * by each test
     */
    const filePath = path.join(outputDir, 'lcov.info')

    /**
     * We nest in a dir because otherwise we will gather
     * json files that bazel itself generates and we wish to avoid
     * gathering.
     */
    if (!fs.existsSync(path.dirname(filePath))) {
      fs.mkdirSync(path.dirname(filePath), { recursive: true })
    }
    // If the lcov file doesn't exist, make one otherwise
    // coverage fails. This applies to non standard file types like
    // html, json, etc.
    if (!fs.existsSync(filePath)) {
      fs.writeFileSync(filePath, '', {
        encoding: 'utf8',
      })
    }
    // Following is taken from https://github.com/aspect-build/rules_jest/blob/940a9fe3c319e1351352e2ffa889e05db790343e/jest/private/jest_config_template.mjs#L151C1-L162
    let coverageFile = path.basename(process.env.COVERAGE_OUTPUT_FILE as string)
    let coverageDirectory = path.dirname(
      process.env.COVERAGE_OUTPUT_FILE as string
    )
    if (process.env.SPLIT_COVERAGE_POST_PROCESSING === '1') {
      // in split coverage post processing mode bazel assumes that the COVERAGE_OUTPUT_FILE
      // will be created by lcov_merger which runs as a separate action with everything in
      // COVERAGE_DIR provided as inputs. so we'll just create the final coverage at
      // `COVERAGE_DIR/split_coverage.dat` which then later moved by merger.sh to final location.
      coverageDirectory = process.env.COVERAGE_DIR as string
      coverageFile = 'coverage.dat'
    }
    // end of rules_js code

    // Write coverage data to a file that Bazel knows how to handle
    await fs.promises.copyFile(
      path.join(outputDir, 'lcov.info'),
      path.join(coverageDirectory, coverageFile)
    )
  }
}
  1. add the teardown to the config
  globalTeardown: path.resolve(__dirname, 'globalTeardown.js'),
@Aghassi Aghassi added the enhancement New feature or request label Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant