2016-08-05 47 views
2

我们的项目中有一些JUnit测试。有没有办法在我们构建应用程序(本地)时运行测试?我们有一个CI服务器,但当我们在本地运行测试失败的应用程序时,获得确认将是非常好的,而不必等待CI或手动选择运行测试的选项。构建应用程序时运行单元测试(Android)

回答

0

您可以编写gradle或ant脚本来构建Android应用程序并执行Junit,您还可以生成代码覆盖率报告。

我已经使用过蚂蚁了,我成功地做到了。

1.You需要在你的应用程序目录创建一个build.xml

<?xml version="1.0" encoding="UTF-8"?> 
<project name="YourAppName" default="help"> 
    <property file="local.properties" /> 
    <property file="build.properties" /> 
    <property file="ant.properties" /> 
    <property environment="env" /> 
    <condition property="sdk.dir" value="${env.ANDROID_HOME}"> 
     <isset property="env.ANDROID_HOME" /> 
    </condition> 
    <loadproperties srcFile="project.properties" /> 
    <fail 
      message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." 
      unless="sdk.dir" 
    /> 
    <import file="custom_rules.xml" optional="true" /> 
    <import file="${sdk.dir}/tools/ant/build.xml" /> 
</project> 

2.You需要在你的应用程序目录创建一个custom_rules.xml

<project xmlns:jacoco="antlib:org.jacoco.ant"> 

    <property name="build.type" value="build" /> 
    <import file="buildnumber.xml"/> 
    <import file="unittest.xml"/> 
    <property name="src.to.unittest.dir.1" value="src" /> 
    <property name="src.to.unittest.dir.2" value="gen" /> 
    <path id="src.to.unittest.path"> 
    <pathelement path="${src.to.unittest.dir.1}"/> 
    <pathelement path="${src.to.unittest.dir.2}"/> 
    </path> 

    <path id="src.of.unittests.path"> 
    <pathelement path="unittests"/> 
    <pathelement path="functests"/> 
    </path> 

    <target name="dev-default"> 

    </target> 

    <target name="-package-resources" depends="-crunch"> 
     <echo>env package suffix: ${env.target.package} </echo> 
     <!-- only package resources if *not* a library project --> 
     <do-only-if-not-library elseText="Library project: do not package resources..." > 
      <aapt executable="${aapt}" 
        manifestPackage="com.yourpackage${env.target.package}" 
        command="package" 
        versioncode="${version.code}" 
        versionname="${version.name}" 
        debug="${build.is.packaging.debug}" 
        manifest="${out.manifest.abs.file}" 
        assets="${asset.absolute.dir}" 
        androidjar="${project.target.android.jar}" 
        apkfolder="${out.absolute.dir}" 
        nocrunch="${build.packaging.nocrunch}" 
        resourcefilename="${resource.package.file.name}" 
        resourcefilter="${aapt.resource.filter}" 
        libraryResFolderPathRefid="project.library.res.folder.path" 
        libraryPackagesRefid="project.library.packages" 
        libraryRFileRefid="project.library.bin.r.file.path" 
        previousBuildType="${build.last.target}" 
        buildType="${build.target}" 
        ignoreAssets="${aapt.ignore.assets}"> 
       <res path="${out.res.absolute.dir}" /> 
       <res path="${resource.absolute.dir}" /> 
      </aapt> 
     </do-only-if-not-library> 
    </target> 
</project> 

3.You需要创建一个unittest.xml在你的应用程序目录:

<project xmlns:jacoco="antlib:org.jacoco.ant"> 

    <!-- IMPORTANT: your project and all library dependencies must be built first 
     then you can run the cobertura-generate-reports task 
    --> 

    <!-- import this file from your Android project custom_rules.xml 

     define these properties: 
     src.to.unittest.dir.1 - required 
     src.to.unittest.dir.2 - optional 
     src.to.unittest.dir.3 - optional 
     src.to.unittest.dir.4 - optional 
      these properties specify the source directories that contain the code that 
      you want to test. 

     commonandroid.classes 
     override this if common is not a sibling of your project dir 

     and these paths: 
     src.to.unittest.path - required 
      use the dir.1 - dir.4 properties above to define 
      this path specifies the code under test that will be built 

     src.of.unittests.path - required 
      this path species the unit test code that will be built 


    --> 

    <property name="shared.externals.dir" value="path/to/android/externals/libs"/> 
<!-- 
    <property name="commonandroid.classes" value="../common/bin/classes" /> 
--> 
    <property name="coverage.report.format" value="xml"/> 
    <property name="cobertura.excludes" value="**/*Tests*"/> 

    <path id="classpath.junit"> 
    <fileset dir="${shared.externals.dir}/junit/4.12" id="fileset.junit"> 
     <include name="junit-4.12.jar"/> 
     <include name="hamcrest-core-1.3.jar"/> 
    </fileset> 
    </path> 

    <path id="classpath.jmockit"> 
    <fileset dir="${shared.externals.dir}/jmockit/1.20" id="fileset.jmockit"> 
     <include name="jmockit.jar"/> 
    </fileset> 
    </path> 

    <path id="classpath.jmockit.coverage"> 
    <fileset dir="${shared.externals.dir}/jmockit/1.20" id="fileset.jmockit.coverage"> 
     <include name="jmockit-coverage.jar"/> 
    </fileset> 
    </path> 
    <path id="classpath.robolectric"> 
    <fileset dir="${shared.externals.dir}/robolectric/3.1" id="fileset.robolectric"> 
     <include name="*.jar"/> 
    </fileset> 
<!-- 
    <fileset dir="${shared.externals.dir}/robolectric/2.4" id="fileset.robolectric"> 
     <include name="robolectric-2.4-jar-with-dependencies.jar"/> 
     <include name="robolectric-2.4-sources.jar"/> 
    </fileset> 
--> 
    </path> 

<!-- 
    <path id="classpath.logback"> 
    <fileset dir="${shared.externals.dir}/logback/1.1.2" id="fileset.logback"> 
     <include name="logback-classic-1.1.2.jar"/> 
     <include name="logback-core-1.1.2.jar"/> 
    </fileset> 
    </path> 
--> 

    <path id="classpath.slf4j"> 
    <fileset dir="${shared.externals.dir}/slf4j/1.7.13" id="fileset.slf4j"> 
     <include name="slf4j-api-1.7.13.jar"/> 
     <include name="slf4j-jdk14-1.7.13.jar"/> 
     <include name="slf4j-log4j12-1.7.13.jar"/> 
    </fileset> 
    </path> 

    <path id="classpath.cobertura2"> 
    <fileset dir="${shared.externals.dir}/cobertura/2.1.1" id="fileset.cobertura2"> 
     <include name="asm-*.jar"/> 
     <include name="cobertura*.jar"/> 
     <include name="oro-2.0.8.jar"/> 
     <include name="commons-lang3*.jar"/> 
     <include name="logback*.jar" /> 
    </fileset> 
    <path refid="classpath.slf4j" /> 
<!-- 
    <path refid="classpath.logback" /> 
--> 
    <pathelement location="."/> 
    </path> 

    <path id="classpath.android"> 
    <fileset dir="${sdk.dir}/platforms/${target}" id="fileset.android"> 
     <include name="android.jar"/> 
    </fileset> 
    </path> 

    <path id="auxClassesPath"> 
    <pathelement location="${commonandroid.classes}"/> 
    <path refid="classpath.android"/> 
    </path> 

    <taskdef classpathref="classpath.cobertura2" resource="tasks.properties"/> 

    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml"> 
     <classpath path="${shared.externals.dir}/jacoco/0.7.8/jacocoant.jar"/> 
    </taskdef> 

    <property name="reports" location="unittest-results"/> 
    <property name="jacoco.coverage.data" location="${reports}/jacoco.exec"/> 
    <property name="classes.unittest.dir" location="${reports}/classes"/> 
    <property name="cobertura.dir" location="${reports}/cobertura"/> 
    <property name="cobertura.build" location="${cobertura.dir}/build"/> 
    <property name="cobertura.dist" location="${cobertura.dir}/dist"/> 
    <property name="cobertura.instr" location="${cobertura.dir}/instr"/> 
    <property name="cobertura.reportsrc" location="${cobertura.dir}/reportsrc"/> 
    <property name="cobertura.jar" value="cobertura-unittests.jar"/> 
    <property name="src.unittests.dir" value="unittests"/> 


    <target name="clean.unittest"> 
    <delete dir="${reports}"/> 
    </target> 

    <target name="init.unittest" depends="clean.unittest"> 
    <mkdir dir="${classes.unittest.dir}"/> 
    <property name="dont.do.deps" value="true"/> 
    </target> 

    <target name="compile.unittest.pathsetup"> 
    <path id="project.javac.classpath"> 
     <path refid="project.all.jars.path" /> 
     <path refid="tested.project.classpath" /> 
     <path refid="classpath.robolectric"/> 
     <path refid="classpath.jmockit"/> 
     <path refid="classpath.junit"/> 
     <path refid="classpath.android"/> 
    </path> 
    </target> 


    <target name="compile.unittest" depends="init.unittest, -build-setup, compile.unittest.pathsetup"> 

    <javac encoding="${java.encoding}" 
      source="${java.source}" target="${java.target}" 
      debug="true" extdirs="" includeantruntime="false" 
      destdir="${classes.unittest.dir}" 
      bootclasspathref="project.target.class.path" 
      verbose="${verbose}" 
      classpathref="project.javac.classpath" 
      fork="${need.javac.fork}"> 
     <src refid="src.to.unittest.path"/> 
     <src refid="src.of.unittests.path"/> 
     <compilerarg line="${java.compilerargs}" /> 
    </javac> 

    <copy todir="${classes.unittest.dir}" failonerror="true" overwrite="true" verbose="true"> 
     <fileset dir="functests" includes="**/*.xml" /> 
    </copy> 
    </target> 

    <target name="jar.unittest" depends="compile.unittest"> 
    </target> 

    <target name="cobertura-clean" depends="jar.unittest"> 
    <delete dir="${cobertura.dir}"/> 
    <delete dir="${cobertura.build}"/> 
    <delete dir="${cobertura.dist}"/> 
    <delete dir="${cobertura.instr}"/> 
    <delete dir="${cobertura.reportsrc}"/> 
    <delete> 
     <fileset dir="${reports}" includes="TEST*.xml"/> 
    </delete> 
    </target> 

    <target name="cobertura-init" depends="cobertura-clean"> 
    <mkdir dir="${cobertura.dir}"/> 
    <mkdir dir="${cobertura.build}"/> 
    <mkdir dir="${cobertura.dist}"/> 
    <mkdir dir="${cobertura.instr}"/> 
    <mkdir dir="${cobertura.reportsrc}"/> 
    </target> 

    <target name="cobertura-instrument" depends="cobertura-init"> 
    <jar destfile="${cobertura.dist}/${cobertura.jar}" update="true"> 
     <fileset dir="${classes.unittest.dir}"> 
     <exclude name="${cobertura.excludes}"/> 
     </fileset> 
    </jar> 

    <cobertura-instrument todir="${cobertura.instr}" datafile="${cobertura.dir}/cobertura.ser"> 
     <fileset dir="${cobertura.dist}"> 
     <include name="${cobertura.jar}"/> 
     </fileset> 
     <auxClasspath refid="auxClassesPath"/> 
    </cobertura-instrument> 
    </target> 

    <target name="cobertura-unit-test" depends="cobertura-instrument"> 
    <echo>project.javac.classpath = ${toString:project.javac.classpath}</echo> 
    <condition property="junit.dir" value="${user.dir}/${basedir}" else="."> 
     <isset property="${basedir}"/> 
    </condition> 
    <echo message="Running JUnit tests in : ${junit.dir}"/> 
    <junit dir="${junit.dir}" 
      showoutput="no" 
      printsummary="on" 
      haltonfailure="no" 
      haltonerror="no" 
      failureproperty="junit.failure" 
      fork="true" 
      forkmode="perTest" 
      maxmemory="512m"> 
     <classpath> 
     <fileset dir="${cobertura.instr}"> 
      <include name="${cobertura.jar}"/> 
     </fileset> 
     <pathelement location="${classes.unittest.dir}"/> 
     <path refid="classpath.cobertura2"/> 
     <path refid="project.javac.classpath"/> 
     </classpath> 
     <jvmarg value="-XX:-UseSplitVerifier"/> 
     <formatter type="xml"/> 
     <sysproperty key="net.sourceforge.cobertura.datafile" file="${cobertura.dir}/cobertura.ser"/> 
     <batchtest todir="${reports}"> 
     <fileset dir="${classes.unittest.dir}"> 
      <include name="**/*MainActivity*Tests.class"/> 
      <include name="**/*FormActivity*Tests.class"/> 
<!-- 
      <include name="**/*Test.class"/> 
      <include name="**/*Tests.class"/> 
--> 
     </fileset> 
     </batchtest> 
    </junit> 

    <junitreport todir="${reports}"> 
     <fileset dir="${reports}"> 
     <include name="TEST-*.xml"/> 
     </fileset> 
     <report format="frames" todir="${reports}/junit"/> 
    </junitreport> 

    <!-- The tests are configured to continue if there is a failure so we can check for more than one--> 
    <!-- failure. So we check if there was at least one failure, if so, we'll fail the build.--> 
    <fail message="One or more unit tests failed" if="junit.failure"/> 
    </target> 

    <target name="report-copy-all-source-files"> 
    <copy todir="${cobertura.reportsrc}" failonerror="false"> 
     <fileset dir="${src.to.unittest.dir.1}" /> 
     <fileset dir="${src.to.unittest.dir.2}" /> 
     <fileset dir="${src.to.unittest.dir.3}" /> 
     <fileset dir="${src.to.unittest.dir.4}" /> 
    </copy> 
    </target> 

    <target name="cobertura-generate-reports" depends="cobertura-unit-test, report-copy-all-source-files"> 
    <cobertura-report destdir="${cobertura.dir}" 
         format="${coverage.report.format}" 
         datafile="${cobertura.dir}/cobertura.ser" srcdir="${cobertura.reportsrc}"> 
    </cobertura-report> 
    </target> 

    <target name="env-unittests"> 
    <property name="env.target.package" value="" /> 
    <property name="env.app.name" value="app_name" /> 
    </target> 

    <target name="build-for-test" depends="env-unittests, clean, debug"/> 

    <target name="build-and-test"> 
    <antcall target="build-for-test"/> 
    <antcall target="jacoco-unit-test"/> 
    <antcall target="jacoco-report"/> 
    <antcall target="jacoco-check-coverage"/> 
    </target> 

    <target name="test"> 
    <antcall target="jacoco-unit-test"/> 
    <antcall target="jacoco-check-coverage"/> 
    </target> 

    <target name="jacoco-unit-test" depends="compile.unittest, copy-test-res"> 
    <echo>project.javac.classpath = ${toString:project.javac.classpath}</echo> 
    <condition property="junit.dir" value="${user.dir}/${basedir}" else="."> 
     <isset property="${basedir}"/> 
    </condition> 
    <echo message="Running JUnit tests in : ${junit.dir}"/> 
    <jacoco:coverage inclnolocationclasses="true" destfile="${jacoco.coverage.data}"> 
    <junit dir="${junit.dir}" 
      showoutput="no" 
      printsummary="on" 
      haltonfailure="no" 
      haltonerror="no" 
      failureproperty="junit.failure" 
      fork="true" 
      forkmode="once" 
      maxmemory="1024m"> 
     <classpath> 
     <pathelement location="${classes.unittest.dir}"/> 
     <path refid="project.javac.classpath"/> 
     </classpath> 
     <formatter type="xml"/> 
     <batchtest todir="${reports}"> 
     <fileset dir="${classes.unittest.dir}"> 
<!-- 
      <include name="**/*MainActivity*Tests.class"/> 
      <include name="**/*FormActivity*Tests.class"/> 
--> 
      <include name="**/*Test.class"/> 
      <include name="**/*Tests.class"/> 
     </fileset> 
     </batchtest> 
    </junit> 
    </jacoco:coverage> 

    <junitreport todir="${reports}"> 
     <fileset dir="${reports}"> 
     <include name="TEST-*.xml"/> 
     </fileset> 
     <report format="frames" todir="${reports}/junit"/> 
    </junitreport> 

    <!-- The tests are configured to continue if there is a failure so we can check for more than one--> 
    <!-- failure. So we check if there was at least one failure, if so, we'll fail the build.--> 
    <fail message="One or more unit tests failed" if="junit.failure"/> 
    </target> 
</project> 
  • 你需要在你的应用程序目录创建一个buildnumber.xml

  • 相关问题