之前写过一个关于怎样生成 html 的东西,当时是通过 java 代码去解析生成的 xml 然后再拼装成 html,感觉那个方法不是很好,太繁琐,后来看到 java 可以利用 ant 来生成 html,于是就试了一下。虽然很不愿意去看 ant 的资料,在各位大神严厉的不严厉的批评下还是硬着头皮大致过了一遍,觉得实现方法比较低端就没写贴,看到今天有小伙伴需要就贴一下,献个丑。

如下为 build.xml 的片断

<target name="test" depends="compile">
        <mkdir dir="report" />
        <junit printsummary="yes" haltonerror="no" haltonfailure="no" fork="yes">
            <formatter type="plain" usefile="false" />
            <formatter type="xml" />
            <test name="com.xxx.TestAll" todir="report" />
            <!--<classpath>
                <pathelement location="bin" />
                <fileset dir="${lib.dir}" includes="*.jar" />
            </classpath>-->
            <classpath refid="classpath.test" />
        </junit>
    </target>

    <target name="report" depends="test">
        <mkdir dir="report/html" />
        <junitreport todir="report">
            <fileset dir="report">
                <include name="TEST-*.xml" />
            </fileset>
            <report todir="report/html" />
        </junitreport>
    </target>

但是问题来了,在 android 代码的 build.xml 文件中通过来执行测试程序总会报 Stub!

TestAll:
    [mkdir] Created dir: E:\git-temp\junit
    [junit] Exception in thread "main" java.lang.RuntimeException: Stub!
    [junit]     at junit.framework.TestResult.<init>(TestResult.java:4)
    [junit]     at org.apache.tools.ant.taskdefs.optional.junit.IgnoredTestResult.<init>(IgnoredTestResult.java:41)
    [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:356)
    [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1179)
    [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:1030)

查了一下

可能不是这个原因,知道原因的还请不吝赐教。

于是决定不用<junit>来执行测试程序。换成执行命令行的方式继续配合<junitreport >来执行,<junitreport >是通过 XSL 将 xml 自动转换成 xml,它会自动生成一个 TESTS-TestSuites.xml,它是所有测试结果的一个汇总,html 文件夹中的 index.xml 就是根据它来显示的。

可以先看一下效果,不嫌丑的可以继续往下看 (这么丑的东西,大神就先闭眼略过吧😄)
因为执行速度慢,我只跑了一个包,没有跑全部

在 jenkins 上用 publish html report 把路径选么 html 就可以实现报告展示。

接下来上代码,边讲边上,由于很少写东西,看不明白的继续问就好。

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="testing_internal" default="junitreport">

    <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" />

    <!-- quick check on sdk.dir -->
    <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" />

     <target name="cleanReport">
         <delete  dir="${junit.output.dir}"></delete>
    </target>
    <!-- 执行测试 -->
    <target name="test" depends="cleanReport">
      <xpath input="${tested.project.dir}/AndroidManifest.xml"
             expression="/manifest/@package" output="tested.package"/>

      <echo>Running tests...</echo>
      <exec executable="${adb}" failonerror="true">
        <arg line="${adb.device.arg}"/>
        <arg value="shell"/>
        <arg value="am"/>
        <arg value="instrument"/>
        <arg value="-w"/>
        <arg value="${tested.package}/${test.runner}"/>
      </exec>
    </target>
<!-- pull -->
    <target name="pull" depends="test">  
      <echo>Downloading XML test report...</echo>
      <mkdir dir="${junit.output.dir}"/>
      <exec executable="${adb}" failonerror="true">
      <arg line="${adb.device.arg}"/>
        <arg value="pull" />
         <arg value="/sdcard/KTJunitTestReport/"/>
        <arg value="${junit.output.dir}/" />
      </exec>
    </target>
    <target name="junitreport" depends="pull">
<!-- 生成报告--> 
      <junitreport todir="${junit.output.dir}">
           <fileset dir="${junit.output.dir}">
               <include name="*-TEST.xml"/>
           </fileset>
           <report format="frames" todir="${junit.output.dir}/html"/>
       </junitreport>

    </target>
</project>

为习惯性伸手党们考虑,把 properties 文件也贴一下吧,虽然这种伸手习惯不太好,但慢慢消化变成自己的就好

ant.properties

tested.project.dir=../ktplay_testing_internal
junit.report.dir=../ktplay_testing_internal
jar.libs=${junit.report.dir}/libs
junit.output.dir=junit-report

test.runner=com.ktplay.testing.PolideaInstrumentationTestRunner
teste.package=com.ktplay.sample
src.dir=src
tested.package=com.ktplay.testing.internal

至于 build.xml 文件我都在重要的地方加了注释,看起来应该不难。

紧接着问题又来了,test.runner 里边的类是哪儿来的?为什么要用它?

1.从哪儿来
这个类是我从https://code.google.com/p/the-missing-android-xml-junit-test-runner/
这个 jar 需要自己改一下,链接里对使用方法也有讲述,也可以找到源码,我在源码的基础上自己小小改动了一下,
之所以要改是因为它生成的 xml 会自己包一个根节点,导致我生成的汇总 TESTS-TestSuites.xml 总是 0kb,去掉就好了,还有一个原因是它生成的报告是写系统文件放入 data/dta/com.xxx.xxx./files/,如果我连没有 root 的手机则无法写入。改完的代码就不发了,大家可以自行下载,根据自己需要去修改。

2.为什么要用它
我试过 junit-report.jar 包,但通过 XSL 总是不能把它生成的 xml 报告转换出来,我觉得可能还是节点名什么的不对应,具体内部实现我也不清楚。
但 PolideaInstrumentationTestRunner 这个类确解决了这一点。

至此重要的环节已经贴完,开始让它跑起来吧。。

可能有些地方写的不是很明白,也不太好,如果哪儿写的不正确还请各位大神指摘点评,像我一相的菜鸟可以尽情提问。


↙↙↙阅读原文可查看相关链接,并与作者交流