Issue with coverage report Dart

Hi,

After updating Sonar to the latest LTA version (2025). We are using the native support for Dart projects, but we have an issue.

Our issue is because SonarQube includes all files from sonar.sources in the coverage calculation, even if they have 0% coverage in filtered_lcov.info

For example after apply the following filter:

lcov --exclude coverage/[lcov.info](http://lcov.info/) \
"*/**/*_vm.dart" "*/**/*_helper.dart" "*/**/*_service.dart" "*/**/*_use_case.dart" \
-o coverage/[filtered_lcov.info](http://filtered_lcov.info/)

the coverage on new code for lib/modules/authentication/ui/views/login/login_wi…/_divider.dart and lib/modules/authentication/ui/views/login/login_model.dart is 0 because is excluding both using the filtered_lcov.info and the coverage for lib/modules/authentication/ui/views/login/login_vm.dart is 93,3%, because is using the filter /**/_vm.dart
But our issue in that moment is that the coverage report % is → (0 + 0 + 93,3%) / 3 = 31,1%
so, even though filtered_lcov.info only includes covered files, SonarQube still analyzes all of sonar.sources and counts uncovered files as 0% in the final calculation.
This makes the analysis results very low many times.
Actually the only option we have found is to use -Dsonar.coverage.exclusions,but it doesn’t seem like a good way to do it…since the amount of files or patterns we want to exclude is very large. We have also tried to use a denial logic with Dsonar.coverage.exclusions, but it doesn’t seem to work (we tried it like this: Dsonar.coverage.exclusions=/*.dart,!/_vm.dart,!**/_helper.dart,!/*_service.dart,!/*_use_case.dart

I don’t know if there is something we are doing wrong or something you could help us with, because I’m sure there must be an easier way to configure it.

Extra info:

Actually our sonar github action is

- name: Run SonarQube Analysis
uses: SonarSource/sonarqube-scan-action@v4.2.1
env:
  SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
  projectBaseDir: .
  args: >
    -Dsonar.projectKey=lodgify_lodgify-flutter
    -Dsonar.projectVersion=${{ env.version }}
    -Dsonar.sources=lib
    -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }}
    -Dsonar.dart.lcov.reportPaths=coverage/filtered_lcov.info
    -Dsonar.pullrequest.key=${{ github.event.pull_request.number }}
    -Dsonar.pullrequest.branch=${{ github.head_ref }}
    -Dsonar.pullrequest.base=${{ github.base_ref }}

Regards,

Hi,

You’re running LCOV with a filter to narrow it’s focus. So it produces a coverage report that only includes a subset of files. Then SonarQube imports that report without the benefit of knowing that you left out */**/*_vm.dart &etc on purpose.

So setting an exclusion - as you’ve discovered - is your best bet.

If you’re passing this as a commandline option, you’re missing the leading - on the -D. If you’re passing it in a properties file, then you should drop that leading D.

I don’t recognize this file path format (which looks like a markdown hyperlink), and I doubt analysis does either.

 
HTH,
Ann

sorry, i don’t know why it was copied with the link i just updated the post with the correct way to use the reportpath flag

and about the Dsonar.coverage.exclusions, we used it with -Dsonar.coverage.exclusions what I meant was that we tried to use an exclusion negation logic. I mean for example with -Dsonar.coverage.exclusions=!/_vm.dart** to exclude everything except what fulfilled the pattern **/_vm.dart trying to do a negation with the !, but that had not worked.
I don’t know if we were doing something wrong, but if not it would be a good feature or it could help us.

anyway I would like to ask what advantage it has to use a filter for the coverage report if the things I have excluded are used to do the average as I said and then it generates that the exclusions have a value of 0% and ruin any average I do with a custom filter.

we’ll try to use the exclusion without any negation logic and if not I will come back to comment on this post, thank you very much for your help!

Hi,

Ah. Yeah, no. Exclusions aren’t that sophisticated. You can use glob patterns, and that’s it.

Uhm… good question?

 
Ann