How does it work?

Here is a small description on how Testslicer discovers which tests are affected by which classes:

  • All classes and test classes are instrumented
  • Test runner (Junit/TestNG) invokes your test
  • All method invocations are recorded by Testslicer as your methods were instrumented
  • All invocation calls and related tests are saved in a repository (.testslicer directory)

Configuring ant tasks (part 1/5)

First things first... just configure all our testslicer tags:

<path id="testslicer.classpath">
        <fileset dir="testslicer/">
                <include name="*.jar" />
        </fileset>
</path>
<taskdef name="pick-tests" classname="br.com.caelum.testslicer.ant.PickTests" classpathref="testslicer.classpath" />
<taskdef name="update-timestamps" classname="br.com.caelum.testslicer.ant.UpdateTimestamps" classpathref="testslicer.classpath" />
<taskdef name="testslicer-instrument" classname="br.com.caelum.testslicer.ant.InstrumentTask" classpathref="testslicer.classpath" />

Instrumenting your java code (part 2/5)

Just after compiling, you have to instrument your java application to run the required testslicer code. Notice that instrumenting test classes and instrumenting app classes is done by setting differente testClasses attribute. This happens so testslicer can better detect a testname whether its running with TestNG or JUnit.

<testslicer-instrument src="target/classes"
        target="target/classes-testslicer"
        testClasses="false">
        <classpath>
                <path refid="build.classpath" />
                <path path="target/classes" />
        </classpath>
</testslicer-instrument>

<testslicer-instrument src="target/test-classes"
        target="target/test-classes-testslicer"
        testClasses="true">
        <classpath>
                <path refid="tests.classpath" />
                <path path="target/test-classes" />
        </classpath>
</testslicer-instrument>

Detecting affected tests (part 3/5)

Prior to running your tests, one needs to select only the affected tests. How to do it? Simply invoke the pickt-tests task, letting us know where are the source directories (to analyze timestamps) and your test fileset. Note the output attribute which creates a file with all selected tests that should run:

<pick-tests output="_ant_test_runner_result.txt" runFullBuildOnNoChangesDetected="true">
        <dirset dir=""> <!-- source code directory to analyze timestamps -->
                <include name="src/main/java"/>
                <include name="src/test/java"/>
        </dirset>
        <fileset>
                <!-- your test fileset here -->
        </fileset>
</pick-tests>

Running the tests (part 4/5)

In order to run junit/testng with our agent you have to add the agent to the vm (and FORK the vm!!!). Do not forget to add testslicer to your classpath too!

  • The most common mistake is to use your non instrumented classes. Remember to add classes-testslicer and test-classes-testslicer to your classpath!*
    <junit fork="yes" forkmode="once" printsummary="true">
            <jvmarg line="-javaagent:testslicer/testslicer-0.9.0.jar"/>
    
            <classpath>
                    <pathelement path="target/classes-testslicer" />
                    <pathelement path="target/test-classes-testslicer" />
                    <pathelement path="testslicer/*.jar" />
            </classpath>
    
            <batchtest fork="yes" todir="${artifacts.dir}/reports">
                    <!-- your test fileset here -->
            </batchtest>
    </junit>

Updating timestamps (part 5/5)

After all tests are SUCESSFULLY completed, remember to register the current file timestamps by invoking the update-timestamps task with your SOURCE directory:

<update-timestamps>
        <dirset dir="">
                <include name="src/main/java"/>
                <include name="src/test/java"/>
        </dirset>
</update-timestamps>