javascript - Sonarqube 不从 LCOV 检索我的 JavaScript 覆盖率

标签 javascript sonarqube code-coverage lcov karma-coverage

我有一个具有以下结构的应用程序:

my-application
  +- pom.xml
  +- app
  |   +- scripts
  |   |   +- app.js
  |   |   +- **/*.js
  |   +- 3rd-party-libs
  +- build
  +- node_modules
  +- test

我创建了 pom.xml 只是为了运行 SonarQube 分析。否则,所有任务都由 Grunt 运行(测试使用 Karma 运行)。

pom.xml 的内容如下:

<properties>
    <sonar.language>js</sonar.language>
    <sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
    <sonar.javascript.coveragePlugin>lcov</sonar.javascript.coveragePlugin>
    <sonar.javascript.lcov.reportPath>build/karma/coverage/lcov.info</sonar.javascript.lcov.reportPath>
    <sonar.exclusions>app/3rd-party-libs/**,node_modules/**</sonar.exclusions>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
</properties>

<build>
    <sourceDirectory>app/scripts</sourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>
</build>

当我运行 grunt test 时,它会创建一个包含以下信息的 build/karma/coverage/lcov.info:

TN:
SF:./app/scripts/app.js
FN:16,(anonymous_1)
FN:26,(anonymous_2)
FNF:2
...

在 SonarQube 分析之后,仪表板显示代码覆盖率为 0%。

我怀疑 SF: 中的路径是错误的来源。因此,我更改了 sonar.javascript.lcov.reportPath 属性以使用另一个 lcov.info 来测试不同的值:app.js , ./app.js, app/scripts/app.js, ./app/scripts/app.js, 但都没有用,将覆盖率保持在 0%。

我错过了什么?

以防万一,我在我的 karma.conf.js 中有以下配置:

coverageReporter: {
  reporters: [
    {
      type: 'lcov',
      dir: 'build/karma/coverage',
      subdir: '.'
    }
  ]
},

ps:Sonar的版本是3.7.2,我也试过4.3的,结果一样。。。


编辑:我已经更新了配置以直接使用 Sonar-runner,我使用的是最新版本的 Sonar (5.0.1) 和 JS 插件 (2.3)。我还手动修改了 lcov.info 以具有“良好”格式(至少一种与 Sonar repo 示例匹配的格式):

SF:./app/scripts/app.js
DA:2,1
DA:20,1
DA:29,1
DA:34,1
end_of_record
SF:./app/scripts/services/exampleService.js
DA:1,1
DA:11,1
DA:12,0
end_of_record

sonar-project.properties 看起来像:

sonar.projectKey=xxx
sonar.projectName=xxx
sonar.projectVersion=xxx
sonar.sourceEncoding=UTF-8

sonar.sources=app/scripts
sonar.tests=test
sonar.exclusions=app/3rd-party-libs/**,node_modules/**
sonar.dynamicAnalysis=reuseReports
sonar.language=js
sonar.projectBaseDir=.
sonar.javascript.coveragePlugin=lcov
sonar.javascript.lcov.reportPath=build/karma/coverage/lcov.info

而且仍然是 0% 的覆盖率 :(

最佳答案

我一无所知,所以我决定修改 JavaScript plugin添加更多日志。我终于找到了错误,这是一个...区分大小写的恶性问题!

让我解释一下。让我们考虑 CoverageSensor.javasaveMeasureFromLCOVFile 方法:

  protected void saveMeasureFromLCOVFile(SensorContext context) {
    String providedPath = settings.getString(JavaScriptPlugin.LCOV_REPORT_PATH);
    File lcovFile = getIOFile(fileSystem.baseDir(), providedPath);
    ...
    LOG.info("Analysing {}", lcovFile);

    LCOVParser parser = new LCOVParser(fileSystem.baseDir());
    Map<String, CoverageMeasuresBuilder> coveredFiles = parser.parseFile(lcovFile);

    for (InputFile inputFile : fileSystem.inputFiles(mainFilePredicate)) {
      try {
        CoverageMeasuresBuilder fileCoverage = coveredFiles.get(inputFile.file().getAbsolutePath());
        org.sonar.api.resources.File resource = org.sonar.api.resources.File.create(inputFile.relativePath());

        if (fileCoverage != null) {
          for (Measure measure : fileCoverage.createMeasures()) {
            context.saveMeasure(resource, measure);
          }
        } else {
          // colour all lines as not executed
          LOG.debug("Default value of zero will be saved for file: {}", resource.getPath());
          LOG.debug("Because: either was not present in LCOV report either was not able to retrieve associated SonarQube resource");
          saveZeroValueForResource(resource, context);
        }
      } catch (Exception e) {
        LOG.error("Problem while calculating coverage for " + inputFile.absolutePath(), e);
      }
   }
  }

首先,它读取给定的 lcov.info 文件以了解我们拥有哪些文件的覆盖率数据(通过解析文件检索,使用 LCOVParser 类完成)。 之后,它从 coveredFiles 映射中获取相同的文件来进行指标和代码之间的匹配。如果找不到文件(if (fileCoverage != null) {else 部分),则代码覆盖率将强制为 0。

这就是我的项目中发生的事情。

那么为什么会这样呢?仅仅是因为在我的环境中,inputFile 等于 d:\dev\my-application\app\scripts\app.js 而在 coveredFiles map ,我有 D:\dev\my-application\app\scripts\app.js。请注意驱动器号中大小写的区别(d:D:)。由于 map.get(...) 区分大小写,fileCoveragenull,因此不计算覆盖率。

现在,我必须研究如何强制路径具有正确的大小写...


经过更多调查,我发现对插件代码的修改有效(至少对我而言,我没有考虑所有可能的影响)。在 LCOVParser , filePath = CoverageSensor.getIOFile(moduleBaseDir, filePath).getCanonicalPath(); 可以修改为 filePath = CoverageSensor.getIOFile(moduleBaseDir, filePath).getAbsolutePath(); ,因为第一个返回类似 D:\... 的路径,而第二个将返回 d:\...

事实上,我什至不知道在 Windows 上使用什么是首选。以下代码:

public static void main(String[] args) throws IOException {
    System.out.println("PATH 1 : " + new File(".").getAbsolutePath());
    System.out.println("PATH 2 : " + new File(".").getCanonicalPath());
}

将返回:

PATH 1 : D:\dev\preclosing\preclosing-eme\.
PATH 2 : D:\dev\preclosing\preclosing-eme

无论如何,我暂时被卡住了,我什至不确定如何在不等待 JS 插件修复的情况下解决我的问题(因为我的“官方”Sonar 目前有点旧并且只支持JS 插件到 v2.1)。

关于javascript - Sonarqube 不从 LCOV 检索我的 JavaScript 覆盖率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28702990/

相关文章:

javascript - Vue.js 2 自动转义 HTML

nullpointerexception - SonarQube Runner 在分析过程中抛出 NullPointerException

未找到 SonarQube Lcov.info

java - SonarLint 插件在 Eclipse Oxygen 中不起作用

c++ - 如何在 Clion 中查看代码覆盖率

javascript - 从 aspx.cs 调用 ASP.NET 母版页 (.Master) 函数

javascript - 未捕获的类型错误 : Cannot read property 'width' of undefined in JavaScript

android - JaCoCo 使用 Kotlin 和 Android 3.0 返回 0% 覆盖率

python - 使 py.test、coverage 和 tox 一起工作 : __init__. py 在测试文件夹中?

javascript - Mongoose gridfs-stream 如何填充 fs.file 集合