Set up Sonar Cloud for Python

Hi,
Please help me with my multi-language project structure
This is my folder structure:
/
__/Python_source
____/Module1
______/Src1
______/Test1
____/Module2
______/Src2
______/Test2
__/

when I run unittest and coverage, i change dir to Python_source so the content looks like this:
image
Tthese file names do not contain Python_source and I also export coverage.xml there
When I configure Sonar Analysis, I point to this directory, but It does not realize that it should added Python_source as a prefix to the path, so my coverage is 0%
Do you have any suggestion to fixed my problem
this is how i create my coverage (from Python_source)
coverage run -m unittest discover -v
coverage xml -i --omit=/opt/*
Thank you

Hello @Le_L_i_Hoang,

First, are you using Automatic Analysis or do you perform the analysis on your own CI?

Please note that if you’re using automatic analysis, the import of coverage information is simply not supported (see here: https://sonarcloud.io/documentation/analysis/automatic-analysis/).

In case you’re not using automatic analysis, would you be able to share the logs of the analysis as well as the properties you use for the analysis (in sonar-project.properties)?

In particular, as indicated in the documentation, is the sonar.python.coverage.reportPaths property set up correctly to import your coverage report? It might be that your coverage report is simply not imported at all.

Thank you,
Guillaume

1 Like

Hi @Le_L_i_Hoang,

As @Guillaume_Dequenne mentioned, coverage reports only work if you run the sonar scanner yourself, and not through automatic analysis. If you are not running the sonar scanner you’ll have to disable the automatic analysis then run the scanner yourself.

For all our python coverage need we use GitHub - CleanCut/green: Green is a clean, colorful, fast python test runner.. It is a fast and simple test coverage runner.

You can use this tiny Makefile or just do the same steps:

# SHELL ensures more consistent behavior between macOS and Linux.
SHELL=/bin/bash

test_reports := build/test_reports/py

.PHONY: *


clean:
	rm -rf build .mypy_cache

pyut:
	rm -rf $(test_reports)
	mkdir -p $(test_reports)
	python3 -m green --run-coverage --junit-report=$(test_reports)/myproject-pytests.xml Python_source
	python3 -m coverage xml -o $(test_reports)/myproject-pycoverage.xml
	python3 -m coverage html -d $(test_reports)/myproject-pycoverage-html
	@echo "HTML code coverage report was generated in $(test_reports)/html"
	@echo "Open it with:"
	@echo "  open $(test_reports)/html/index.html"

For the green target, you can list the path to each module on the same line, it will work just fine.

You want to use that approach since the test reports must have the same relative, or absolute, paths so that the scanner can map the files properly. If you run the tests by running them from the subdirectories then the paths will not match.

We then just set these in our sonar-project.properties file:

sonar.projectBaseDir = ${env.WORKSPACE}
sonar.sources = ${env.WORKSPACE}
# sonar.tests cannot overlap with sources.
# sonar.tests = ${env.WORKSPACE}

# Let Sonar find the sources and tests.
# sonar.sources = ${env.WORKSPACE}
# sonar.tests = ${env.WORKSPACE}/tests
sonar.sourceEncoding =  UTF-8


# Analysis Scope
# https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/
sonar.exclusions = \
  ${env.SONAR_ADDITIONAL_EXCLUSIONS},\
  build/**,\
  **/vendor/**,\
  **/test/test_*.py,\
  **/*_pb2.py

sonar.coverage.exclusions = \
  setup.py,\
  **/test/test_*.py

sonar.python.coverage.reportPaths = ${env.TEST_REPORTS_DIR}/py/*-pycoverage.xml

We set TEST_REPORTS_DIR to the build/test_reports directory and WORKSPACE is the directory where we clone the repository.

I you do not run the sonar scanner yet, I would recommend that you make it work without the test reports first, then add the test coverage analysis. Sonar can be a bit tricky to get configured right.

2 Likes