最后我设法让它工作,我想与你分享解决方案:
为您的 buildType 启用检测并相应地配置 SonarQube,例如
...
apply plugin: 'jacoco'
...
android {
...
productFlavors {
acceptance {
applicationId packageName + ".acceptance"
buildTypes {
debug {
testCoverageEnabled true
}
}
}
}
}
sonarRunner {
sonarProperties {
property "sonar.host.url", "..."
property "sonar.jdbc.url", sonarDatabaseUrl
property "sonar.jdbc.driverClassName", sonarDatabaseDriverClassName
property "sonar.jdbc.username", sonarDatabaseUsername
property "sonar.jdbc.password", sonarDatabasePassword
property "sonar.sourceEncoding", "UTF-8"
property "sonar.sources", "src/main"
property "sonar.tests", "src/test"
property "sonar.inclusions", "**/*.java,**/*.xml"
property "sonar.import_unknown_files", "true"
property "sonar.java.binaries", "build/intermediates/classes/acceptance/debug"
property "sonar.junit.reportsPath", "build/test-results/acceptanceDebug"
property "sonar.android.lint.report", "build/outputs/lint-results.xml"
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.jacoco.reportPath", "build/jacoco/testAcceptanceDebugUnitTest.exec"
// see steps below on how to get that file:
property "sonar.jacoco.itReportPath", "build/jacoco/jacoco-it.exec"
property "sonar.projectKey", projectKey
property "sonar.projectName", projectName
property "sonar.projectVersion", appVersionName
}
}
将以下内容添加到您的 AndroidManifest.xml
<receiver
android:name=".util.CoverageDataDumper"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="org.example.DUMP_COVERAGE_DATA"/>
</intent-filter>
</receiver>
CoverageDataDumper 应该如下所示:
public class CoverageDataDumper extends BroadcastReceiver {
private static final Logger LOG = LoggerFactory.getLogger( CoverageDataDumper.class );
@Override
public void onReceive( Context context, Intent intent ) {
try {
Class
.forName( "com.vladium.emma.rt.RT" )
.getMethod( "dumpCoverageData", File.class, boolean.class, boolean.class )
.invoke( null,
new File( App.getContext().getExternalFilesDir( null ) + "/coverage.ec" ),
true, // merge
false // stopDataCollection
);
}
catch ( Exception e ) {
LOG.error( "Error when writing coverage data", e );
}
}
}
然后使用验收风格应用程序(带有检测类)运行您的 Appium 测试用例。在调用“重置应用程序”或“关闭应用程序”之前,请确保调用以下方法(只是一个草稿,但我想你明白了):
// intent is "org.example.DUMP_COVERAGE_DATA"
public void endTestCoverage( String intent ) {
if ( driver instanceof AndroidDriver ) {
((AndroidDriver) driver).endTestCoverage( intent, "" );
}
}
public void pullCoverageData( String outputPath ) {
String coverageFilePath = (String) appiumDriver.getCapabilities().getCapability( "coverageFilePath" );
if ( coverageFilePath != null ) {
byte[] log = appiumDriver.pullFile( coverageFilePath );
MobileAppLog.writeLog( new File( outputPath ), log );
}
else {
throw new AppiumLibraryNonFatalException(
"Tried to pull the coverage data, but the coverageFilePath wasn't specified." );
}
}
例如,输出路径可以是:/sdcard/Android/data/org.example.acceptance/files/coverage.ec
现在 Jacoco 数据被写入智能手机。接下来我们需要下载该文件。您可以使用
appiumDriver.pullFile( logFilePath );
现在您需要将文件“jacoco-it.exec”(在拉取文件时应始终附加)复制到 build/jacoco/jacoco-it.exec 参见上面的 gradle.build 并运行
gradlew sonarRunner
在 SonarQube 添加集成测试覆盖小部件,您现在应该看到一些值...
不幸的是,如果您使用retrolambda(就像我们一样),代码覆盖将不起作用。Retrolambda 将生成不属于源文件的匿名类 - 因此 SonarQube 无法正确匹配它们,并且显示的代码覆盖率比实际低得多。如果有人找到解决方案,我会很高兴:-)