Sonarqube没有从LCOV检索我的JavaScript报道

时间:2015-02-24 18:01:44

标签: 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.jsapp/scripts/app.js,{{1} },但没有一个工作,保持覆盖率为0%。

我缺少什么?

以防万一,我在./app/scripts/app.js中有以下配置:

karma.conf.js

ps:声纳版本是3.7.2,但我也试过4.3,结果相同......


编辑:我已更新配置以直接使用Sonar-runner,我使用最新版本的Sonar(5.0.1)和JS插件(2.3)。我还手动修改了coverageReporter: { reporters: [ { type: 'lcov', dir: 'build/karma/coverage', subdir: '.' } ] }, ,以便有一个好的&#34; format(至少一种与Sonar repo示例匹配的格式):

lcov.info

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

仍然是0%的报道:(

1 个答案:

答案 0 :(得分:6)

我很无能,所以我决定修改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映射中获取相同的文件来进行指标和代码之间的匹配。如果找不到该文件(else的{​​{1}}部分),则代码覆盖范围将强制为0.

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

那么为什么会这样呢?仅仅因为在我的环境中,if (fileCoverage != null) {等于inputFile,而在d:\dev\my-application\app\scripts\app.js地图中,我有coveredFiles。请注意驱动器号中的案例差异(D:\dev\my-application\app\scripts\app.jsd:)。由于D:区分大小写,map.get(...)fileCoverage,因此不计算任何覆盖率。

现在,我必须调查如何强制路径有正确的案例......


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

事实上,我甚至不知道在Windows上使用的首选案例。以下代码:

d:\...

将返回:

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

无论如何,我暂时陷入困境,我甚至不确定如何在不等待JS插件修复的情况下解决我的问题(因为我的“官方”声纳现在有点老了而且只支持JS插件到v2.1)。