GithubHelp home page GithubHelp logo

vitest-sonar-reporter's Introduction

vitest-sonar-reporter

Version Downloads Compatibility with vitest@latest

Live examples | Installation | Configuration | Code coverage | Examples


SonarQube reporter for Vitest

Generates Generic Execution reports from vitest tests for SonarQube to analyze.

Live examples

Installation

vitest-sonar-reporter should be included in development dependencies. vitest is required as peer dependency.

npm install --save-dev vitest-sonar-reporter

Configuration

Add new custom reporter and define outputFile in your vite.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
    test: {
        reporters: [
            'default', // Vitest's default reporter so that terminal output is still visible
            ['vitest-sonar-reporter', { outputFile: 'sonar-report.xml' }],
        ],
    },
});

If you are using Vitest below version ^1.3.0 you can define file in test.outputFile:

test: {
    reporters: ['json', 'verbose', 'vitest-sonar-reporter'],
    outputFile: {
        json: 'my-json-report.json',
        'vitest-sonar-reporter': 'sonar-report.xml',
    },
},

Instruct SonarQube to pick report in your sonar-project.properties:

sonar.testExecutionReportPaths=sonar-report.xml

Options

You can pass additional options to reporter. Note that this requires vitest@^1.3.0.

silent

Silence reporter's verbose logging.

test: {
    reporters: [
        ['vitest-sonar-reporter', { silent: true }]
    ],
}

onWritePath

Rewrite path attribute of <file>. This can be useful when you need to change relative paths of the files.

test: {
    reporters: [
        ['vitest-sonar-reporter', {
            onWritePath(path: string) {
                // Prefix all paths with root directory
                // e.g. '<file path="test/math.ts">' to '<file path="frontend/test/math.ts">'
                return `frontend/${path}`;
            }
        }]
    ],
}
<testExecutions version="1">
-  <file path="test/math.ts">
+  <file path="frontend/test/math.ts">
    <testCase name="multiply" duration="123" />
  </file>
</testExecutions>

outputFile

Location for the report.

test: {
    reporters: [
        ['vitest-sonar-reporter', { outputFile: 'sonar-report.xml' }]
    ],
}

Code Coverage

This reporter does not process code coverage - Vitest already supports that out-of-the-box!

Simply configure vitest to output LCOV reports and instruct SonarQube to pick these reports.

test: {
    coverage: {
        reporters: 'lcov',
    },
},
sonar.javascript.lcov.reportPaths=./coverage/lcov.info

Examples

Workspace

See examples/example-workspace for example setup using Vitest Workspaces.

Basic

import { describe, expect, test } from 'vitest';

describe('animals', () => {
    test('dogs say woof', () => {
        const dog = { say: () => 'woof' };
        expect(dog.say()).toBe('woof');
    });

    test.todo('figure out what rabbits say', () => {
        const rabbit = { say: () => '????' };
        expect(rabbit.say()).toBe('?');
    });

    describe('flying ones', () => {
        test('cats can fly', () => {
            const cat = { fly: () => false };
            expect(cat.fly()).toBe(true);
        });

        test('birds can fly', () => {
            const bird = { fly: () => true };
            expect(bird.fly()).toBe(true);
        });
    });
});
<testExecutions version="1">
  <file path="test/animals.test.ts">
    <testCase name="animals - dogs say woof" duration="2" />
    <testCase name="animals - figure out what rabbits say" duration="0">
      <skipped message="figure out what rabbits say" />
    </testCase>
    <testCase name="animals - flying ones - cats can fly" duration="4">
      <failure message="expected false to be true // Object.is equality">
        <![CDATA[AssertionError: expected false to be true // Object.is equality
    at /workspaces/example/test/animals.test.ts:15:47
    at /workspaces/example/node_modules/vitest/dist/chunk-runtime-chain.7032872a.js:82:26
    at runTest (/workspaces/example/node_modules/vitest/dist/entry.js:771:40)
    at async runSuite (/workspaces/example/node_modules/vitest/dist/entry.js:836:13)
    at async runSuite (/workspaces/example/node_modules/vitest/dist/entry.js:836:13)
    at async runSuite (/workspaces/example/node_modules/vitest/dist/entry.js:836:13)
    at async runFiles (/workspaces/example/node_modules/vitest/dist/entry.js:873:5)
    at async startTests (/workspaces/example/node_modules/vitest/dist/entry.js:879:3)
    at async /workspaces/example/node_modules/vitest/dist/entry.js:906:7
    at async withEnv (/workspaces/example/node_modules/vitest/dist/entry.js:503:5)]]>
      </failure>
    </testCase>
    <testCase name="animals - flying ones - birds can fly" duration="5" />
  </file>
</testExecutions>

vitest-sonar-reporter's People

Contributors

renovate[bot] avatar ariperkkio avatar bobgneu avatar itouoti12 avatar

Stargazers

jpb06 avatar Mohamad Irfan avatar Daichi Kimura avatar  avatar Jed avatar 唯然 avatar Isaac Graves avatar Naoto Ida avatar Asakura Mizu avatar Diego Vivanco avatar Rafael Oliveira avatar DKKs avatar Dan Harten avatar Gene Chulkov avatar Marcelo Dias avatar InfiniteXyy avatar Patrick Young avatar Gabriel Mocanu avatar  avatar Lukas Elmer avatar Yufan You avatar Juga Paazmaya avatar Ivica Čardić avatar Felix avatar PutziSan avatar Loy Charles avatar Benjamin Cass avatar  avatar Jonathan Picazo avatar

Watchers

James Cloos avatar  avatar  avatar

vitest-sonar-reporter's Issues

Monorepo path issue

Hi,

There is an issue with the file contents path in line 40 when the package is being used in a monorepo. The problem is that the path generated within the package only, rather than a full relative path. This results in SonarQube throwing the following errors:


123012:32:53.502 INFO: Imported test execution data for 0 files
123112:32:53.503 INFO: Test execution data ignored for 12 unknown files, including:
1232 tests/components/foo.spec.ts
1233 tests/components/bar.spec.ts


To resolve this issue, you may want to consider modifying the path to generate a full relative path that includes the monorepo directory. This should ensure that SonarQube is able to properly import the test execution data.

With best regards,
Ioannis

Error: EBADF: bad file descriptor, write

Hi Guys!
Recently, I got an Unhandled Rejection after rerunning tests on change.

Error: EBADF: bad file descriptor, write
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
"code": "EBADF",
"errno": -9,
"syscall": "write",
}

Report failling with vitest 0.25.5

When upgrading to vitest 0.25.5 the tests are failing with:

Error: Failed to load custom Reporter from vitest-sonar-reporter
 ❯ loadCustomReporterModule node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:9194:11
 ❯ async file:/tmp/jhlite/vueapp/node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:9207:32
 ❯ Vitest.setServer node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:10575:170
 ❯ configureServer node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:11395:11
 ❯ createServer node_modules/vite/dist/node/chunks/dep-5605cfa4.js:62117:24
 ❯ createVitest node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:11427:18
 ❯ startVitest node_modules/vitest/dist/chunk-vite-node-externalize.ca4784be.js:11543:15
 ❯ start node_modules/vitest/dist/cli.js:701:17
 ❯ CAC.run node_modules/vitest/dist/cli.js:680:3

Caused by: Error: [vite-node] Failed to load ./sonar-reporter.js
 ❯ ViteNodeRunner.directRequest node_modules/vitest/dist/chunk-vite-node-source-map.d0aa773d.js:237:13

Ex of a failing dependabot build: https://github.com/jhipster/jhipster-lite/actions/runs/3646191190/jobs/6157124260

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): update all non-major dependencies (@types/node, eslint-plugin-import, typescript-eslint, vite)

Detected dependencies

github-actions
.github/actions/run-example/action.yml
.github/actions/setup-and-cache/action.yml
  • actions/setup-node v4
  • actions/cache v4
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/checkout v4
.github/workflows/publish.yml
  • actions/checkout v4
  • actions/setup-node v4
.github/workflows/vitest-latest-compatibility.yml
  • actions/checkout v4
  • actions/checkout v4
npm
package.json
  • @eslint/eslintrc ^3.1.0
  • @eslint/js ^9.9.1
  • @types/eslint ^9.6.1
  • @types/node ^22.5.2
  • eslint ^9.9.1
  • eslint-config-prettier ^9.1.0
  • eslint-plugin-import ^2.29.1
  • eslint-plugin-prettier ^5.2.1
  • eslint-plugin-unicorn ^55.0.0
  • prettier ^3.3.3
  • publint ^0.2.10
  • typescript ^5.5.4
  • typescript-eslint ^8.3.0
  • vite ^5.4.2
  • vitest ^2.0.5

  • Check this box to trigger a request for Renovate to run again on this repository

ERR_REQUIRE_ESM

I have a Vue3 + TS app, when i set it up according to instructions : add the package via yarn, modify vite.config.ts, when i try to run the tests, i get this error :

Error [ERR_REQUIRE_ESM]: require() of ES Module ~site/node_modules/vitest-sonar-reporter/dist/index.js from ~site/apps/surf-essentials/web-store/vite.config.ts not supported.
Instead change the require of index.js in ~site/apps/surf-essentials/web-store/vite.config.ts to a dynamic import() which is available in all CommonJS modules.
at Object. (~site/apps/surf-essentials/web-store/vite.config.ts:41:44)
at Object.require.extensions. [as .ts] (~site/node_modules/vite/dist/node/chunks/dep-9c153816.js:71416:20)
at loadConfigFromBundledFile (~site/node_modules/vite/dist/node/chunks/dep-9c153816.js:71424:17)
at loadConfigFromFile (~site/node_modules/vite/dist/node/chunks/dep-9c153816.js:71343:32)
at async resolveConfig (~site/node_modules/vite/dist/node/chunks/dep-9c153816.js:70873:28)
at async createServer (~site/node_modules/vite/dist/node/chunks/dep-9c153816.js:56425:20)
at async createVitest (file://~site/node_modules/vitest/dist/chunk-vite-node-externalize.458f885a.js:10752:18)
at async startVitest (file://~site/node_modules/vitest/dist/chunk-vite-node-externalize.458f885a.js:10837:15)
at async CAC.start (file://~site/node_modules/vitest/dist/cli.js:664:9) {
code: 'ERR_REQUIRE_ESM'
}

I tried changing the "type": "module" in the package.json, but it breaks the project.

Should i do something additional ?? How can i get this package to work with this project ?

Test not (visible) running with `vitest-sonar-reporter`

With this vitest.config.ts, and the command npx vitest --pool=forks --run --coverage, I get no visual feedback that the tests have run. I know that the tests are running, but no output is given, only the text coverage and SonarQube report written to…

import { defineConfig, mergeConfig } from 'vitest/config';

import viteConfig from './vite.config';

export default defineConfig(async (configEnv) =>
  mergeConfig(
    viteConfig(configEnv),
    defineConfig({
      test: {
        globals: true,
        typecheck: {
          tsconfig: './tsconfig.test.json'
        },
        snapshotFormat: {
          printBasicPrototype: true
        },
        environment: 'jsdom',
        include: ['src/**/__tests__/**/*.[jt]s?(x)'],
        coverage: {
          provider: 'v8',
          reporter: ['text'],
          include: ['src/**/*.[jt]s?(x)']
        },
        reporters: 'vitest-sonar-reporter',
        outputFile: 'reports/coverage/sonar-report.xml',
        setupFiles: ['./src/config/tests/setupTests.ts']
      }
    })
  )
);

Option to silence output

I don't want to see the "SonarQube report written to" line in the test output, so I'd like an option to silence it.

RangeError: Maximum call stack size exceeded

Details

I used this library to migrate from Jest to vitest.
I currently have 388 test files in my project and when I set up this library to create a reporter for SonarQube and ran vitest, I got the following error.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
RangeError: Maximum call stack size exceeded
 ❯ generateXml node_modules/vitest-sonar-reporter/dist/xml.js:58:12
 ❯ SonarReporter.onFinished node_modules/vitest-sonar-reporter/dist/sonar-reporter.js:37:35
 ❯ node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10640:51
 ❯ Vitest.report node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10638:38
 ❯ node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10475:18
 ❯ processTicksAndRejections node:internal/process/task_queues:96:5
 ❯ Vitest.runFiles node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10479:12
 ❯ Vitest.start node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:10406:5
 ❯ startVitest node_modules/vitest/dist/chunk-vite-node-externalize.6b27b039.mjs:11140:5

Cause
src/xml.ts

export function generateXml(files?: File[]) {
    return join(
        '<testExecutions version="1">',
        NEWLINE,
        ...(files?.map(generateFileElement).join(NEWLINE) || []),
        NEWLINE,
        '</testExecutions>'
    );
}

Spread Operator causes some timing to be broken down into an array of one character at a time

[
  ' ', ' ', '<', 'f', 'i', 'l', 'e',  ' ', 'p', 'a', 't',
  'h', '=', '"', 's', 'r', 'c', '/',  'p', 'a', 'g', 'e',
  's', 
  ... 491 more items
]

The spread operator (and Array.assign) loads the entire source array onto the stack, then pushes it onto the destination array. Once the source array exceeds 125,052, it causes a Stack Overflow / Range Error.

Suggestion

export function generateXml(files?: File[]) {
    return join(
        '<testExecutions version="1">',
        NEWLINE,
        (files?.map(generateFileElement).join(NEWLINE) || []),
        NEWLINE,
        '</testExecutions>'
    );
}

Thanks for creating this wonderful library.

Issue with format for when transforming test-report.xml

For some reason, the reporter generates this:

<testExecutions version="1">
  <file pat<testsuites name="vitest tests" tests="6" failures="0" errors="0" time="0.8">
    <testsuite name="src/utils/example.test.ts" timestamp="2024-06-27T11:21:16.165Z" hostname="the-system.local" tests="1" failures="0" errors="0" skipped="0" time="0.001">
        <testcase classname="src/utils/example.test.ts" name="example &gt; returns expected value" time="0.001">
        </testcase>
    </testsuite>
</testsuites>

As you might see, the path part is incorrectly formatted. When I downgrade to version 1.1.0 it works fine.

Undefined config in this.ctx

package.json

{
  "exports": "./index.js",
  "node": ">=14.16",
  "scripts": {
    "lint": "eslint --fix --cache ./ || true",
    "test": "vitest --watch",
    "testCoverage": "vitest run --coverage --passWithNoTests --reporter verbose",
    "sonar": "node ./sonar.js",
    "testanalyze": "vitest run --coverage --passWithNoTests --reporter verbose && node ./sonar.js",
    "webstorm-integration": "vitest --watch --reporter=dot --reporter=json --outputFile=.vitest-result.json"
  },
  "type": "module",
  "devDependencies": {
    "@vitest/coverage-c8": "^0.25.4",
    "c8": "^7.12.0",
    "eslint": "^8.29.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "msw": "^0.49.1",
    "sonarqube-scanner": "^2.9.1",
    "vite": "^3.2.5",
    "vitest": "^0.25.4",
    "vitest-sonar-reporter": "^0.3.3"
  }
}

vite.config.ts

import { configDefaults, defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    exclude: configDefaults.exclude,
    testTimeout: 30000,
    reporters: 'vitest-sonar-reporter',
    outputFile: 'coverage/sonar-report.xml',
    coverage: {
      reporter: ['lcov']
    }
  },
})

Error

SonarQube report written to /path/to/project/coverage/sonar-report.xml
file:///path/to/project/node_modules/vitest-sonar-reporter/dist/sonar-reporter.js:19
        const reportFile = resolve(this.ctx.config.root, this.outputFile);
                                            ^

TypeError: Cannot read properties of undefined (reading 'config')
    at SonarReporter.onFinished (file:///path/to/project/node_modules/vitest-sonar-reporter/dist/sonar-reporter.js:19:45)
    at file:///path/to/project/node_modules/vitest/dist/chunk-vite-node-externalize.ddcbafa3.js:10918:51
    at Array.map (<anonymous>)
    at Vitest.report (file:///path/to/project/node_modules/vitest/dist/chunk-vite-node-externalize.ddcbafa3.js:10916:38)
    at file:///path/to/project/node_modules/vitest/dist/chunk-vite-node-externalize.ddcbafa3.js:10753:20
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Vitest.runFiles (file:///path/to/project/node_modules/vitest/dist/chunk-vite-node-externalize.ddcbafa3.js:10760:12)
    at async Vitest.start (file:///path/to/project/node_modules/vitest/dist/chunk-vite-node-externalize.ddcbafa3.js:10673:5)

Node.js v19.2.0

sonar-report.xml not generated

For some reason the sonar-report.xml file is not being generated.

relevant parts of package.json

{
  "devDependencies": {
    "@vitest/coverage-c8": "^0.27.1",
    "c8": "^7.12.0",
    "sonarqube-scanner": "^3.0.0",
    "vite": "^4.0.4",
    "vitest": "^0.27.1",
    "vitest-sonar-reporter": "^0.3.3"
  }
}

vite.config.ts

import { configDefaults, defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    exclude: configDefaults.exclude,
    testTimeout: 30000,
    reporters: 'vitest-sonar-reporter',
    outputFile: 'coverage/sonar-report.xml',
    coverage: {
      reporter: ['lcov']
    }
  },
})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.