Reporting coverage for .NET solutions with VB.NET and C# projects

Must-share information (formatted with Markdown):

  • which versions are you using (SonarQube, Scanner, Plugin, and any relevant extension): 8.1 Enterprise
  • what are you trying to achieve: Report OpenCover report for a solution with mixed VB.NET and C# project
  • what have you tried so far to achieve this: Passing OpenCover report to sonar.cs.opencover.reportsPaths and sonar.vbnet.opencover.reportsPaths

We have .NET solutions with mixed languages (some projects in VB.NET, some in C#). We have coverage results for test runs of these solutions available in OpenCover format. Coverage files are not on a project level, but only available for the whole solution.

Sonar Scanner has different parameters for passing coverage files for C# and VB.NET (sonar.cs.opencover.reportsPaths and sonar.vbnet.opencover.reportsPaths). If a soluiton is either VB.NET or fully C#, coverage reporting works fine by passing files to the appropriate parameters. How are we supposed to pass coverage files if a solution contains projects in different languages? Passing coverage files to both parameters seems to lead to an error in the scanner.

Hello Pascal,

Could you please share with us the detailed error message you get when doing this ?
Is it also possible for you to run the analysis with verbose mode enabled, and share the detailed logs of the end step of the analysis ? That would be greatly helpful in finding out where the issue is coming from.

Thanks.
Regards,

-Chris

Relevant part is here:

Begin / SonarScanner for MSBuild 4.8
-----------------------------------------------------

begin 
/d:sonar.host.url="[REDACTED]" 
/k:"[REDACTED]" 
/d:sonar.cs.nunit.reportsPaths="C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\nunit-results-*.xml" 
/d:sonar.vbnet.nunit.reportsPaths="C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\nunit-results-*.xml" 
/d:sonar.cs.opencover.reportsPaths="C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\opencover-results-*.xml" 
/d:sonar.vbnet.opencover.reportsPaths="C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\opencover-results-*.xml" 
/d:sonar.pullrequest.provider="vsts" 
/d:sonar.pullrequest.branch="[REDACTED]" 
/d:sonar.pullrequest.key="[REDACTED]" 
/d:sonar.pullrequest.base="[REDACTED]" 
/d:sonar.login="[REDACTED]" 
/d:sonar.pullrequest.vsts.instanceUrl=[REDACTED]
/d:sonar.pullrequest.vsts.project=[REDACTED]
/d:sonar.pullrequest.vsts.repository=[REDACTED]
/d:sonar.verbose=true

End 
-----------------------------------------------------

[09:57:14] :		 [End-SonarScanner] 09:57:14.105 INFO: Adding this code coverage report to the cache for later reuse: C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\opencover-results-2182424.xml
[09:57:14] :		 [End-SonarScanner] 09:57:14.107 DEBUG: Analyzing coverage after aggregate found '56' coverage files.
[09:57:14] :		 [End-SonarScanner] 09:57:14.289 DEBUG: The total number of file count statistics is '56'.
[09:57:14] :		 [End-SonarScanner] 09:57:14.289 INFO: Coverage Report Statistics: 56 files, 56 main files, 56 main files with coverage, 0 test files, 0 project excluded files, 0 other language files.
[09:57:14] :		 [End-SonarScanner] 09:57:14.289 INFO: Sensor VB.NET Tests Coverage Report Import [vbnet] (done) | time=248068ms
[09:57:14] :		 [End-SonarScanner] 09:57:14.289 INFO: Sensor VB.NET Unit Test Results Import [vbnet]
[09:57:14] :		 [End-SonarScanner] 09:57:14.290 DEBUG: Pattern matcher extracted prefix/absolute path 'C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports' from the given pattern 'C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\nunit-results-*.xml'.
[09:57:14] :		 [End-SonarScanner] 09:57:14.290 DEBUG: Gathering files for wildcardPattern 'nunit-results-*.xml'.
[09:57:14] :		 [End-SonarScanner] 09:57:14.290 DEBUG: Pattern matcher returns '1' files.
[09:57:14] :		 [End-SonarScanner] 09:57:14.290 DEBUG: The current user dir is 'C:\Build Agent\work\3a9ccf275d7f1e27'.
[09:57:14] :		 [End-SonarScanner] 09:57:14.290 INFO: Parsing the NUnit Test Results file 'C:\Build Agent\work\3a9ccf275d7f1e27\dist\logs\opencoverreports\nunit-results-2182424.xml'.
[09:57:14] :		 [End-SonarScanner] 09:57:14.309 DEBUG: Parsed NUnit test run - total: 3033, totalSkipped: 332, failures: 1, errors: 1, execution time: 1477664.
[09:57:14] :		 [End-SonarScanner] 09:57:14.332 INFO: ------------------------------------------------------------------------
[09:57:14] :		 [End-SonarScanner] 09:57:14.332 INFO: EXECUTION FAILURE
[09:57:14] :		 [End-SonarScanner] 09:57:14.332 INFO: ------------------------------------------------------------------------
[09:57:14] :		 [End-SonarScanner] 09:57:14.332 INFO: Total time: 8:41.574s
[09:57:14] :		 [End-SonarScanner] 09:57:14.461 INFO: Final Memory: 43M/359M
[09:57:14] :		 [End-SonarScanner] 09:57:14.461 INFO: ------------------------------------------------------------------------
[09:57:14]E:		 [End-SonarScanner] 09:57:14.461 ERROR: Error during SonarQube Scanner execution
[09:57:14]E:		 [End-SonarScanner] java.lang.UnsupportedOperationException: Can not add the same measure twice on [key=[REDACTED]]: 
[09:57:14]E:		 [End-SonarScanner] DefaultMeasure[component=[key=[REDACTED]],metric=Metric[id=<null>,key=tests,description=Number of unit 
[09:57:14]E:		 [End-SonarScanner] tests,type=INT,direction=1,domain=Coverage,name=Un
[09:57:14]E:		 [End-SonarScanner] it Tests,qualitative=false,userManaged=false,enabled=true,worstValue=<null>,bestValue=<null>,optimizedBestValue=false,h
[09:57:14]E:		 [End-SonarScanner] idden=false,deleteHistoricalData=false,decimalScale=<null>],value=3033,fromCore=false,storage=org.sonar.scanner.sensor.
[09:57:14]E:		 [End-SonarScanner] DefaultSensorStorage@66482ba8,saved=false]
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.sensor.DefaultSensorStorage.saveMeasure(DefaultSensorStorage.java:177)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.sensor.DefaultSensorStorage.store(DefaultSensorStorage.java:137)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.api.batch.sensor.measure.internal.DefaultMeasure.doSave(DefaultMeasure.java:96)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.api.batch.sensor.internal.DefaultStorable.save(DefaultStorable.java:45)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.plugins.dotnet.tests.UnitTestResultsImportSensor.analyze(UnitTestResultsImportSensor.java:85)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.plugins.dotnet.tests.UnitTestResultsImportSensor.execute(UnitTestResultsImportSensor.java:74)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:48)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:85)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:62)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:82)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:386)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:382)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:351)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:141)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:72)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:66)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
[09:57:14]E:		 [End-SonarScanner] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[09:57:14]E:		 [End-SonarScanner] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[09:57:14]E:		 [End-SonarScanner] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[09:57:14]E:		 [End-SonarScanner] 	at java.lang.reflect.Method.invoke(Method.java:498)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
[09:57:14]E:		 [End-SonarScanner] 	at com.sun.proxy.$Proxy0.execute(Unknown Source)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.cli.Main.execute(Main.java:112)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.cli.Main.execute(Main.java:75)
[09:57:14]E:		 [End-SonarScanner] 	at org.sonarsource.scanner.cli.Main.main(Main.java:61)
[09:57:14] :		 [End-SonarScanner] Process returned exit code 1
[09:57:14]E:		 [End-SonarScanner] The SonarQube Scanner did not complete successfully
[09:57:14]E:		 [End-SonarScanner] 09:57:14.519  Post-processing failed. Exit code: 1
[09:57:14]E:		 [End-SonarScanner] An error occurred when executing task '
[09:57:14]E:		 [End-SonarScanner] End-SonarScanner'.
[09:57:14]E:		 [End-SonarScanner] Error while finishing Sonar scanner.
[09:57:14]E:		 [End-SonarScanner] : Cake.Core.CakeException: SonarQube: Process returned an error (exit code 1).
[09:57:14]E:		 [End-SonarScanner]    at Cake.Core.Tooling.Tool`1.ProcessExitCode(Int32 exitCode)
[09:57:14]E:		 [End-SonarScanner]    at Cake.Core.Tooling.Tool`1.Run(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings 
[09:57:14]E:		 [End-SonarScanner] processSettings, Action`1 postAction)
[09:57:14]E:		 [End-SonarScanner]    at Cake.Sonar.SonarRunner.Run(SonarSettings settings)
[09:57:14]E:		 [End-SonarScanner]    at Submission#0.SonarEnd(SonarEndSettings settings)
[09:57:14]E:		 [End-SonarScanner]    at Submission#0.<<Initialize>>b__0_130(BuildData buildData)
[09:57:14]E:		 [End-SonarScanner]    at Cake.Core.CakeTaskBuilderExtensions.<>c__DisplayClass32_0.<Does>b__0(ICakeContext x)
[09:57:14]E:		 [End-SonarScanner]    at Cake.Core.CakeTask.<Execute>d__43.MoveNext()
[09:57:14]E:		 [End-SonarScanner] --- End of stack trace from previous location where exception was thrown ---
[09:57:14]E:		 [End-SonarScanner]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[09:57:14]E:		 [End-SonarScanner]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[09:57:14]E:		 [End-SonarScanner]    at Cake.Core.DefaultExecutionStrategy.<ExecuteAsync>d__4.MoveNext()
[09:57:14]E:		 [End-SonarScanner] --- End of stack trace from previous location where exception was thrown ---
[09:57:14]E:		 [End-SonarScanner]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[09:57:14]E:		 [End-SonarScanner]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

Hello Pascal,

Thanks for the quick reply as well as providing detailed logs of the analysis. This was a great help to investigate the issue.
Looking at the logs and after some investigation on our side, it seems the issue is not coming from the coverage reports, but from the nunit unit test reports. I have created a corresponding ticket to fix this issue.

In the meantime, you can deactivate one of the 2 nunit report import. You should still be able to import both opencover coverage reports into SonarQube.

Hope that helps.

Regards,

-Chris

@pascalberger we are having problems with project where VB and C# is in one solution without code coverage usage and tests.

May be you can share how to you managed to work SonarQube on such solution here: Problem with .NET framework with VB and C# in one solution (not code coverage)

Thank you in advance!