Stephane-Gon
Stephane-Gon

Reputation: 89

Run cypress code coverage on pipeline job

So I decided to integrate Sonarqube into a project, and now I want to send it the coverage report of my cypress e2e tests.

I have a Vite React application with cypress e2e tests, and to add coverage reports I use nyc, vite-plugin-istanbul and @cypress/code-coverage. When I run my tests locally the report is generated and it seems correct but when I run the tests on a pipeline job the tests run and pass but no coverage is created.

This is the job in my .gitlab-ci.yml file where the tests are running:

e2e-tests:
  image: 
    name: node:20.9.0
    entrypoint: ['']
  stage: e2e-test
  only:
    - merge_requests
    - main
  variables:
    # Change to true to run on QA environment
    CI: 'false'
  before_script:
    - apt-get update -qq && apt-get install -y
    - apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
  script:
    - export NODE_ENV=test
    - yarn cypress install --force
    - yarn install
    - yarn test:ci-e2e-server
  artifacts:
    paths:
      - e2e-coverage/

This is the script I use to run the tests:

 "test:ci-e2e-server": "start-server-and-test start http://localhost:5173 'cypress run'",

Here I use the start-server-and-test package to create a server on the pipeline in order to start my server on a localhost and run my tests.

This is my vite.config.ts file:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import eslint from 'vite-plugin-eslint';
import istanbul from 'vite-plugin-istanbul';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    istanbul({
      extension: ['.js', '.ts', '.jsx', '.tsx'],
      requireEnv: false,
      nycrcPath: './.nycrc.json',
      cypress: true,
    }),
    react({
      babel: {
        plugins: [
          [
            'babel-plugin-styled-components',
            {
              displayName: true,
              fileName: false,
            },
          ],
        ],
      },
    }),
    eslint(),
  ],
  resolve: {
    alias: [{ find: '@', replacement: '/src' }],
  },
  server: {
    host: true,
  },
});

This is the configuration on my .nycrc.json:

{
  "extends": "@istanbuljs/nyc-config-typescript",
  "all": true,
  "check-coverage": false,
  "include": "src/*",
  "exclude": [
    "cypress/**",
    "coverage/**",
    "instrumented/**",
    "backstop/**",
    "unit-coverage/**",
    "e2e-coverage/**",
    "node_modules",
    ".nyc_output"
  ],
  "report-dir": "e2e-coverage",
  "reporter": ["lcov"]
}

And on my next.config.ts I have this setupNodeEvents function on my e2e object:

async setupNodeEvents(
      on: Cypress.PluginEvents,
      config: Cypress.PluginConfigOptions,
    ): Promise<Cypress.PluginConfigOptions> {
      coverageTask(on, config);
      // https://github.com/badeball/cypress-cucumber-preprocessor/blob/master/docs/quick-start.md
      await addCucumberPreprocessorPlugin(on, config);

      on(
        'file:preprocessor',
        createBundler({
          plugins: [createEsbuildPlugin(config)],
        }),
      );

      return config;
    },

I also have these properties on my sonar-project.properties

    sonar.sources=src, cypress
    sonar.tests=src, cypress
    sonar.test.inclusions=**/*.test.ts, **/*.test.tsx
    sonar.javascript.lcov.reportPaths=**/lcov.info

The message I get on my job is:

Cannot find coverage file /builds/ahresp-ppec-e2r/e2r-area-reservada/.nyc_output/out.json Skipping coverage report

Aditional information:

Upvotes: 1

Views: 1049

Answers (1)

Stephane-Gon
Stephane-Gon

Reputation: 89

So in case someone is also struggling with this, here is what I did to solve this problem.

So first I added a .env.test file with a VITE_NODE_ENV variable set to test.

Then in my job I updated it to this:

e2e-tests:
  image: 
    name: node:20.9.0
    entrypoint: ['']
  stage: e2e-test
  only:
    - development
    - main
  variables:
    # Change to true to run on QA api
    CI: 'false'
  script:
    - export VITE_NODE_ENV=test
    - apt-get update -qq && apt-get install -y
    - apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
    - yarn cypress install --force
    - yarn install
    - yarn test:ci-e2e-server
  artifacts:
    paths:
      - e2e-coverage/

I created a new script to start the server in test mode:

"start:test": "vite --mode test",

and I also updated the test:ci-e2e-server script:

"test:ci-e2e-server": "start-server-and-test start:test 5173 'cypress run'",

And to finish I my config I get the VITE_NODE_ENV variable and enable coverage if it's test.

import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import eslint from 'vite-plugin-eslint';
import istanbul from 'vite-plugin-istanbul';

// https://vitejs.dev/config/
export default ({ mode }) => {
  process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };

  return defineConfig({
    plugins: [
      istanbul({
        extension: ['.js', '.ts', '.jsx', '.tsx'],
        requireEnv: process.env.VITE_NODE_ENV !== 'test', // Set to true to enable coverage
        nycrcPath: './.nycrc.json',
        cypress: true,
      }),
      react({
        babel: {
          plugins: [
            [
              'babel-plugin-styled-components',
              {
                displayName: true,
                fileName: false,
              },
            ],
          ],
        },
      }),
      eslint(),
    ],
    resolve: {
      alias: [{ find: '@', replacement: '/src' }],
    },
    server: {
      host: true,
    },
  });
};

Upvotes: 2

Related Questions