How do I run JUnit tests during my Ant build scrip

2020-02-14 05:07发布

I'm using the Hello World with Ant tutorial from the Ant manual to learn about Ant.

The last part of the tutorial involves adding JUnit tests to the project.

I've got everything working as described in the tutorial and am now going on to make some minor changes.

One of the changes I would like to make is to run the tests during a typical build but not have the *Test.class files end up in the final .jar file for the application. This is because the eventual project I will be working on will be for a device with limited hard drive space and support for only a subset of the Java SDK so I would prefer to just omit these test files entirely from the jar.

How do I do this?

It would be easy enough to create two separate jars, one for testing and one for deployment, but this seems less than ideal.

My current build.xml file is below.

<property name="src.dir"     value="src"/>

<property name="build.dir"   value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir"     value="${build.dir}/jar"/>
<property name="lib.dir"     value="lib"/>
<property name="report.dir"  value="${build.dir}/junitreport"/>


<property name="main-class"  value="oata.HelloWorld"/>

<path id="classpath">
    <fileset dir="${lib.dir}" includes="**/*.jar"/>
    <path location="[LocalPath]/junit-4.8.2.jar"/>
</path>

<path id="application" location="${jar.dir}/${ant.project.name}.jar"/>

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

<target name="compile">
    <mkdir dir="${classes.dir}"/>
    <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
    <copy todir="${classes.dir}">
        <fileset dir="${src.dir}" excludes="**/*.java"/>
    </copy>
</target>

<target name="jar" depends="compile">
    <mkdir dir="${jar.dir}"/>
    <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
        <manifest>
            <attribute name="Main-Class" value="${main-class}"/>
        </manifest>
    </jar>
</target>

 <target name="junit" depends="jar">
     <mkdir dir="${report.dir}"/>
     <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
        <classpath>
            <path refid="classpath"/>
            <path refid="application"/>
        </classpath>

        <formatter type="xml"/>

        <batchtest fork="yes">
            <fileset dir="${src.dir}" includes="*Test.java"/>
        </batchtest>
    </junit>
</target>

<target name="junitreport" depends="junit">
    <junitreport todir="${report.dir}">
        <fileset dir="${report.dir}" includes="TEST-*.xml"/>
        <report todir="${report.dir}"/>
    </junitreport>
</target>

<target name="run" depends="junit">
    <java fork="true" classname="${main-class}">
        <classpath>
            <path refid="classpath"/>
            <path refid="application"/>
        </classpath>
    </java>
</target>

<target name="clean-build" depends="clean,junit"/>

<target name="main" depends="clean,run"/>

One thing I have tried is modifying the jar command to exclude the *Test.class files

...
<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}" excludes="**/*Test.class">
...

which successfully excludes the test classes but then when the tests are run via the junit target it fails with the following stack trace when run with -v:

[LocalPath]\build.xml:44: Test HelloWorldTest failed
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.actOnTestResult(JUnitTask.java:1863)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:814)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1808)
        at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:760)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
        at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:390)
        at org.apache.tools.ant.Target.performTasks(Target.java:411)
        at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1397)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1366)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1249)
        at org.apache.tools.ant.Main.runBuild(Main.java:801)
        at org.apache.tools.ant.Main.startAnt(Main.java:218)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

2条回答
太酷不给撩
2楼-- · 2020-02-14 05:30

Can you change:

<target name="jar" depends="compile">
    <mkdir dir="${jar.dir}"/>
    <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
        <manifest>
            <attribute name="Main-Class" value="${main-class}"/>
        </manifest>
    </jar>
</target>

to:

<target name="jar" depends="junit">
    <mkdir dir="${jar.dir}"/>
    <jar destfile="${jar.dir}/${ant.project.name}.jar">
        <fileset dir="${classes.dir}" excludes="**/*Test.class"/>
        <manifest>
            <attribute name="Main-Class" value="${main-class}"/>
        </manifest>
    </jar>
</target>

 <target name="junit" depends="compile">
     <mkdir dir="${report.dir}"/>
     <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
        <classpath>
            <path refid="classpath"/>
            <path refid="application"/>
        </classpath>

        <formatter type="xml"/>

        <batchtest fork="yes">
            <fileset dir="${src.dir}" includes="*Test.java"/>
        </batchtest>
    </junit>
</target>

That should exclude the Test classes I believe from the final JAR file.

n.b The change in dependencies for each of the tasks.

查看更多
▲ chillily
3楼-- · 2020-02-14 05:48

Based on @Jon's advice I changed the junit target to run against the build/classes folder instead of the jar and updated the dependencies appropriately.

My updated build.xml file is below:

<project name="HelloWorld" basedir="." default="main">

    <property name="src.dir"     value="src"/>

    <property name="build.dir"   value="build"/>
    <property name="classes.dir" value="${build.dir}/classes"/>
    <property name="jar.dir"     value="${build.dir}/jar"/>
    <property name="lib.dir"     value="lib"/>
    <property name="report.dir"  value="${build.dir}/junitreport"/>

    <property name="main-class"  value="oata.HelloWorld"/>

    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
        <path location="[LocalPath]/junit-4.8.2.jar"/>
    </path>

    <path id="application" location="${jar.dir}/${ant.project.name}.jar"/>

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

    <target name="compile">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
        <copy todir="${classes.dir}">
            <fileset dir="${src.dir}" excludes="**/*.java"/>
        </copy>
    </target>

    <target name="jar" depends="junit">
        <mkdir dir="${jar.dir}"/>
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}" excludes="**/*Test.class">
            <manifest>
                <attribute name="Main-Class" value="${main-class}"/>
            </manifest>
        </jar>
    </target>

    <target name="junit" depends="compile">
        <mkdir dir="${report.dir}"/>
        <junit printsummary="yes" haltonfailure="yes" showoutput="yes">
            <classpath>
                <path refid="classpath"/>
                <path location="${classes.dir}"/>
            </classpath>

            <formatter type="xml"/>

            <batchtest fork="yes">
                <fileset dir="${src.dir}" includes="*Test.java"/>
            </batchtest>
        </junit>
    </target>

    <target name="junitreport" depends="junit">
        <junitreport todir="${report.dir}">
            <fileset dir="${report.dir}" includes="TEST-*.xml"/>
            <report todir="${report.dir}"/>
        </junitreport>
    </target>

    <target name="run" depends="jar">
        <java fork="true" classname="${main-class}">
            <classpath>
                <path refid="classpath"/>
                <path refid="application"/>
            </classpath>
        </java>
    </target>

    <target name="clean-build" depends="clean,jar"/>

    <target name="main" depends="clean,run"/>

</project>
查看更多
登录 后发表回答