apply plugin: 'org.sonarqube'
allprojects {
group = libGroupId
version = libVersionName
}
sonarqube {
properties {
property 'sonar.scm.provider', 'git'
property 'sonar.scm.url', 'scm:git:path/to/git/repo'
}
}
\:demo-app.sonar.java.test.binaries=path/to/demo-app/build/intermediates/classes/test/debug
\:player-exo.sonar.java.test.binaries=path/to/player-exo/build/intermediates/classes/test/debug
\:player-ui.sonar.java.test.binaries=path/to/player-ui/build/intermediates/classes/test/debug
\:player.sonar.java.test.binaries=path/to/player/build/intermediates/classes/test/debug
player-ui and player-exo actually have Android Instrumentation tests, but their binary path is "$MODULE/build/intermediates/classes/androidTest/debug". Furthermore, neither "demo-app" nor "player" have JVM-based unit tests, so this configuration is completely bogus.
We're using Retrolambda and the plugin seems to pick this up, but again incomplete:
$ grep retrolambda dump.properties
\:demo-app.sonar.binaries=/Users/thomas/Entwicklung/Kunden/maxdome/android-videoplayer/demo-app/build/retrolambda/debug
\:demo-app.sonar.java.binaries=/Users/thomas/Entwicklung/Kunden/maxdome/android-videoplayer/demo-app/build/retrolambda/debug
It only finds retrolambda for the "demo-app" module, but actually there is such a directory for every module:
$ find . -name "retrolambda"
./demo-app/build/retrolambda
./player/build/retrolambda
./player-exo/build/retrolambda
./player-ui/build/retrolambda
What the plugin also completely misses is player-{ui,exo}/build/retrolambda/debugAndroidTest, i.e. retrolambda output for android tests.
Android projects also often run lint on their sources, so do we. The Sonarqube scanner however does not find these files automatically:
$ find . -name "lint-results*.xml"
./demo-app/build/outputs/lint-results-debug.xml
./player/build/outputs/lint-results-debug.xml
./player-exo/build/outputs/lint-results-debug.xml
./player-ui/build/outputs/lint-results-debug.xml
and consequently does not configure them for "sonar.android.lint.report". For flavored builds these files carry the flavor name as well, i.e. "build/outputs/lint-results-<camelCasedFlavorName>{Debug,Release}.xml
Furthermore, neither Android-Test results nor Code Coverage files of those tests are found automatically. These usually reside in "build/outputs/androidTest-results/connected" (for non-flavored builds, otherwise in "build/outputs/androidTest-results/connected/flavors/<UPPERCASE_FLAVOR_NAME>") and "build/outputs/code-coverage/connected/<DEVICE_OR_EMULATOR_NAME>-coverage.ec" (for non-flavored builds, otherwise "build/outputs/code-coverage/connected/flavors/<UPPERCASE_FLAVOR_NAME>/<DEVICE_OR_EMULATOR_NAME>-coverage.ec").
Regarding code coverage: Modern Android projects (and we're talking about nothing else) can only use Jacoco as code coverage tool, as this is the only coverage tool that is supported by Android's instrumentation and Unit tests, so this plugin should be configured as default for Android projects:
sonar.core.codeCoveragePlugin=jacoco
Here another feature request: Since https://jira.sonarsource.com/browse/SONAR-4101 is still not solved (having the ability to report JVM test and instrumentation test results at the same time), you might want to do some magic within the plugin and copy the test results of both tests (JVM and Instrumentation tests) to a common place (say "build/sonarqube/combined-test-results") that is then set as "sonar.junit.reportsPath".
When using modules in sub-directories (i.e. notated through ":libs/foo", ":libs/bar" in settings.gradle), the plugin creates weird paths in the resulting properties file:
\:libs.\:libs\:foo.<some-sonar-property>
\:libs.\:libs\:bar.<some-sonar-property>
I'd have expected something along these lines:
\:libs\:foo.<some-sonar-property>
\:libs\:bar.<some-sonar-property>
or even just
\:foo.<some-sonar-property>
\:bar.<some-sonar-property>
So, in the current state the plugin is not very helpful for Android analysis, because too many things are missing or even wrong and one should rather reside to manual configuration of analysis parameter.
@Sonarsource: If you need help figuring out more of the nitty-gritty details, contact me via PM. I really want to see first-class Android support in Sonarqube Gradle analysis and am here to help.
Thomas.
I'm trying to analyze an Android multi-module project with the Sonarqube Gradle Scanner, version 2.1. There are four Gradle modules on the top level, "player", "player-ui", "player-exo" and "demo-app":
The analysis parameters that result from such a configuration however are largely incomplete or even wrong:$ ./gradlew sonarqube -DsonarRunner.dumpToFile=dump.properties$ grep test.binaries dump.properties\:demo-app.sonar.java.test.binaries=path/to/demo-app/build/intermediates/classes/test/debug
\:player-exo.sonar.java.test.binaries=path/to/player-exo/build/intermediates/classes/test/debug
\:player-ui.sonar.java.test.binaries=path/to/player-ui/build/intermediates/classes/test/debug
\:player.sonar.java.test.binaries=path/to/player/build/intermediates/classes/test/debug
player-ui and player-exo actually have Android Instrumentation tests, but their binary path is "$MODULE/build/intermediates/classes/androidTest/debug".
public interface TestedVariant {
/**
* Returns the build variant that will test this build variant.
*
* <p>The android test variant exists only for one build type, by default "debug". This is
* controlled by {@link TestedAndroidConfig#getTestBuildType}.
*/
@Nullable
TestVariant getTestVariant();
/**
* Returns the build variant that contains the unit tests for this variant.
*/
@Nullable
UnitTestVariant getUnitTestVariant();
}
Furthermore, neither "demo-app" nor "player" have JVM-based unit tests, so this configuration is completely bogus.
We're using Retrolambda and the plugin seems to pick this up, but again incomplete:
$ grep retrolambda dump.properties
\:demo-app.sonar.binaries=/Users/thomas/Entwicklung/Kunden/maxdome/android-videoplayer/demo-app/build/retrolambda/debug
\:demo-app.sonar.java.binaries=/Users/thomas/Entwicklung/Kunden/maxdome/android-videoplayer/demo-app/build/retrolambda/debug
It only finds retrolambda for the "demo-app" module, but actually there is such a directory for every module:[...]
What the plugin also completely misses is player-{ui,exo}/build/retrolambda/debugAndroidTest, i.e. retrolambda output for android tests.
Android projects also often run lint on their sources, so do we. The Sonarqube scanner however does not find these files automatically:
and consequently does not configure them for "sonar.android.lint.report". For flavored builds these files carry the flavor name as well, i.e. "build/outputs/lint-results-<camelCasedFlavorName>{Debug,Release}.xml
Furthermore, neither Android-Test results nor Code Coverage files of those tests are found automatically. These usually reside in "build/outputs/androidTest-results/connected" (for non-flavored builds, otherwise in "build/outputs/androidTest-results/connected/flavors/<UPPERCASE_FLAVOR_NAME>") and "build/outputs/code-coverage/connected/<DEVICE_OR_EMULATOR_NAME>-coverage.ec" (for non-flavored builds, otherwise "build/outputs/code-coverage/connected/flavors/<UPPERCASE_FLAVOR_NAME>/<DEVICE_OR_EMULATOR_NAME>-coverage.ec").
Regarding code coverage: Modern Android projects (and we're talking about nothing else) can only use Jacoco as code coverage tool, as this is the only coverage tool that is supported by Android's instrumentation and Unit tests, so this plugin should be configured as default for Android projects:
sonar.core.codeCoveragePlugin=jacoco
Here another feature request: Since https://jira.sonarsource.com/browse/SONAR-4101 is still not solved (having the ability to report JVM test and instrumentation test results at the same time), you might want to do some magic within the plugin and copy the test results of both tests (JVM and Instrumentation tests) to a common place (say "build/sonarqube/combined-test-results") that is then set as "sonar.junit.reportsPath".
When using modules in sub-directories (i.e. notated through ":libs/foo", ":libs/bar" in settings.gradle), the plugin creates weird paths in the resulting properties file:
\:libs.\:libs\:foo.<some-sonar-property>\:libs.\:libs\:bar.<some-sonar-property>
So, in the current state the plugin is not very helpful for Android analysis, because too many things are missing or even wrong and one should rather reside to manual configuration of analysis parameter.
@Sonarsource: If you need help figuring out more of the nitty-gritty details, contact me via PM. I really want to see first-class Android support in Sonarqube Gradle analysis and am here to help.
Thomas.
I don't know much about the Gradle internals, but I can tell you there
is an important difference between test and unit test variant.
Basically, Android Tooling has support for native (running on emulator /
device) and non-native (running on standard VM) tests. [...]
And here is another catch: Since all these variants exist, I think it is
not enough to just look out for the first variant with a "debug" build
type for either test type, since many such variants could exist and also
could have been executed prior to the plugin execution (assembled
binaries and test results "at the right place" would hint you on their
execution).
Well, no, it is not crashing the analysis, but I'd have thought the
plugin would have figured out that I have no "src/*test*" directories,
hence no JVM unit tests and therefor skip this configuration.
> We're using Retrolambda and the plugin seems to pick this up, but
> again incomplete:
> [...]
> It only finds retrolambda for the "demo-app" module, but actually
> there is such a directory for every module:[...]
Again, I don't know much of the internals here, but there have to be
other destination dirs as well, because the "retrolambda" one is really
only one very special, 3rd party library that brings back some of the
Java 8 features to the dreaded Android Java-kind-of-7 world. It is
completely optional, but often included in projects nonetheless.
> What the plugin also completely misses
> is player-{ui,exo}/build/retrolambda/debugAndroidTest, i.e.
> retrolambda output for android tests.
Yes, I figured as much. I'll try and make a small example project that shows
* separate sources by flavor
* separate unit / instrumentation tests by flavors
* referenced library modules
* source, binary, lint, code coverage and test result configuration
based on "best guesses" in a separated sonar-project.properties file
I hope this will help you a little.
Some time back I hacked together a Gradle plugin to retrieve POM
contents (name, description, url, author, ...) for each listed
dependency in an Android application. What I learned there was to start
from the active application variants the Android build model gives you
(you should not build this list of variants up yourself, because
developers have the possibility to remove "non-existing" variants of
multi-dimensional configurations from this list that makes no sense) and
then build up the paths and things yourself.
Yes, this is tedious and might not be needed for everything, but with
some internal understanding you quickly have something workable and
robust. And whether the build tools change some API (which they do quite
often) or change paths of things in the filesystem is then neglectable,
you'd have to adapt your plugin anyways.
To support multi-variant runs that drop multiple *.ec files after
execution, I'd also say jacoco.itReportPath and jacoco.reportPath should
be extended to allow globs like their junit counterparts.
In any way, files that originate from instrumentation test runs on
devices will be dynamically named, because the name of the connected
device(s) is not available at the time Gradle completed its
configuration phase, so you'll always either have to scan the suspected
output directories or work with globs (if this becomes available).
Actually I was shocked that it was so little useful, though it was
dubbed to replace the tedious manual configuration via
sonar-project.properties, but then again, if you have no Android experts
on your team it is hard to get all this information.
android {
...
testBuildType "staging"
}