本文介绍了Android的摇篮Jacoco:离线仪器仪表集成测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在建立一个Android应用程序是通过使用Appium测试。现在,我希望看到我们的Appium测试的测试覆盖率。我认为这是可能的,因为Jacoco支持离线仪器仪表(http://www.eclemma.org/jacoco/trunk/doc/offline.html).

we are building an Android app which is tested by using Appium. Now I would like to see the test coverage of our Appium tests.I think this is possible, because Jacoco supports offline instrumentation (http://www.eclemma.org/jacoco/trunk/doc/offline.html).

而jacoco摇篮插件甚至文件说:

And even the documentation of the jacoco gradle plugin says:

而型式试验的所有任务都自动增强,可提供覆盖信息当Java插件已被应用,实现JavaForkOptions任何任务可以由JaCoCo插件增强。也就是说,任何任务叉Java进程可以用于生成覆盖信息。

看https://docs.gradle.org/current/userguide/jacoco_plugin.html

但我怎么都写build.gradle所以我们的验收调试味道仪表和EXEC文件写入到智能手机的Appium测试执行,甚至手工测试用例执行时?因为这样我可以提取EXEC文件,并把它使SonarQube作进一步的分析。

But how do I have to write the build.gradle so our acceptance debug flavor is instrumented and the exec file is written to the Smartphone when the Appium tests are executed or even manual test cases are executed?Because then I can extract the exec file and send it so SonarQube for further analysis.

谢谢本

推荐答案

最后,我设法它得到它的工作,我想分享的解决方案与您:

Finally I managed it to get it working and I want to share the solution with you:

启用仪器为您buildType并相应地配置SonarQube例如,

enable instrumentation for your buildType and configure SonarQube accordinglye.g.

...
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
    }
}

以下内容添加到您的Andr​​oidManifest.xml

add the following to your AndroidManifest.xml

<receiver
 android:name=".util.CoverageDataDumper"
 tools:ignore="ExportedReceiver">
 <intent-filter>
    <action android:name="org.example.DUMP_COVERAGE_DATA"/>
 </intent-filter>
</receiver>

CoverageDataDumper应该看起来像:

CoverageDataDumper should look like that:

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测试用例验收味应用程序(与仪表类)。你所说的复位应用程序或关闭应用程序之前,请务必拨打下面的方法(只是一个草案,但我认为你的想法):

Then run your Appium test cases with the acceptance flavor app (with instrumented classes). Before you call "Reset App" or "Close Application" make sure to call the following methods (just a draft, but I think you get the idea):

// 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." );
  }
}

outputPath可以是例如:/sdcard/Android/data/org.example.acceptance/files/coverage.ec

outputPath could be for example: /sdcard/Android/data/org.example.acceptance/files/coverage.ec

现在的Jacoco数据被写入到智能手机。接下来,我们需要下载该文件。您可以使用

Now the Jacoco data is written to the Smartphone. Next we need to download that file. You can use

appiumDriver.pullFile( logFilePath );

现在,你需要复制该文件jacoco-it.exec(这应该永远是的,当你拉文件)到构建/ jacoco / jacoco-it.exec看到gradle.build上面并运行

Now you need to copy the file "jacoco-it.exec" (which should always be appended when you pull the file) into build/jacoco/jacoco-it.exec see gradle.build above and run

gradlew sonarRunner

在SonarQube添加集成测试覆盖率的Widget,你现在应该看到一些值...

In SonarQube add the Integration Test Coverage Widget and you should see now some values...

不幸的是,如果你使用的是retrolambda(和我们一样)code覆盖率将无法工作。 Retrolambda将产生匿名类而不是源文件的一部分 - 所以SonarQube不能正确地匹配它们并显示低得多的code覆盖范围比实际的。如果有人发现了一个解决方案,我会非常高兴: - )

这篇关于Android的摇篮Jacoco:离线仪器仪表集成测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 15:01