Section 6.3. Testing a Plug-in


6.3. Testing a Plug-in

If you're writing a plug-in for general consumption, it would be good if you could ensure that it is working fine. You don't want to release something buggy, right? This lab will show you how to write automated tests for your plug-in.

6.3.1. How do I do that?

You can write two types of tests: Java unit tests and functional tests. Writing Java unit tests makes sense only if your plug-in is relying on Java source code. You add JUnit tests to your plug-in project just as you do for any Maven project: you add them to an src/test directory defined using the unitTestSourceDirectory element in your project.xml file. When you execute the plugin:install goal, your unit tests will run automatically.

As most Maven plug-ins rely on Jelly script, it makes more sense to focus on writing functional tests than it does to focus on JUnit tests. The Plugin plug-in has a special plugin:test goal which automatically starts your functional tests, provided you have put them in the src/plugin-test directory. A functional test is simply a Maven project that you put in src/plugin-test. This Maven test project has to meet only one condition: it must have a custom goal named testPlugin that you write in its maven.xml file. Under the hood, this is the goal that will be called when you execute the plugin:test goal.

As you might need several functional tests for your plug-in, the best practice is to set up a Multiproject project in src/plugin-test. For example, for the Jarexec plug-in you might want to write a first test to verify that it can run a test JAR using the default JAR location (name this project testDefaultJarExecution) and a second test showing it can run a JAR that you specify using the mdn.jarexec.jar property (name this project testJarExecutionWhenSpecifyingLocation). The full directory structure will then be (see Figure 6-2):


src/plugin-test

The location of the master Multiproject project.


src/plugin-test/testDefaultJarExecution

The location of the functional test for testing default JAR execution. It also contains a Java class (Main.java) that is used to generate a test JAR.


src/plugin-test/testJarExecutionWhenSpecifyingLocation

The location of the functional test for testing when the JAR location is specified using the mdn.jarexec.jar property. It also contains required Java sources for the test.

Figure 6-2. Jarexec project showing the functional test directory structure


The src/plugin-test/maven.xml file contains a testPlugin goal that simply triggers the call of the testPlugin goals of all the subprojects, using the multiproject:goal goal (see Chapter 3 for a detailed introduction to the Multiproject project):

<project default="testPlugin" xmlns:j="jelly:core">      <goal name="testPlugin">     <j:set var="goal" value="testPlugin"/>     <attainGoal name="multiproject:goal"/>   </goal>    </project>


Tip: It's good practice to define a default testPlugin goal for test plug-ins (as shown earlier) so that when users type maven directly into their directories they will execute the tests.

The src/plugin-test/project.xml file is a standard POM defining all the elements common to all subprojects. Each subproject only needs to define what's different. For example, src/plugin-test/testDefaultJarExecution/project.xml contains:

<?xml version="1.0"?>    <project>   <extend>../project.xml</extend>   <artifactId>jarexec-testDefaultJarExecution</artifactId>   <name>jarexec-testDefaultJarExecution</name> </project>

Have a look at the code for the testDefaultJarExecution project. The Main.java class is the simplest possible code for generating an executable JAR:

package mdn.jarexec.test;    public class Main {     public static void main(String[  ] args)     {         System.out.println("It works...");     } }

The testDefaultJarExecution/maven.xml file is where the test really happens. You start by cleaning the project to ensure that the test starts in a good state, and then you execute the jarexec:run goal. As a final step, you run assertions to verify that the outcome was successful:

<project default="testPlugin"   xmlns:ant="jelly:ant"   xmlns:assert="assert">      <goal name="testPlugin" prereqs="clean">        <ant:mkdir dir="${maven.build.dir}"/>     <ant:record name="${maven.build.dir}/log.txt" action="start"/>     <attainGoal name="jarexec:run"/>     <ant:record name="${maven.build.dir}/log.txt" action="stop"/>        <assert:assertFileContains file="${maven.build.dir}/log.txt"          match="It works..."/>      </goal>    </project>

The difficult part in this case is asserting that the Main class prints the It works... text in the console. One solution that is used here is to record the console output using the Ant record task and then use the assert tag library to verify that the recorded file contains the string you're looking for. The assert tag library is located in the Plugin plug-in. The assertFileContains tag is a new tag introduced in Version 1.6 of the Plugin plug-in. Make sure you have at least this version installed (see Appendix A for directions on installing a specific version of a plug-in).


Tip: In addition to exposing goals, plug-ins can also contribute tag libraries. This is the case for the Plugin plug-in, which offers an assert tag library. A Jelly script can define a new tag library using the Jelly define tag library (see http://jakarta.apache.org/commons/jelly/libs/define/tags.html for reference documentation). To use a tag defined in another plug-in simply define its namespace as you did earlier for the assert tag library: xmlns:assert="assert".

Now you can run the plug-in test by executing the plugin:test goal:

C:\dev\mavenbook\code\plugins\jarexec>maven plugin:test [...] +---------------------------------------- | Executing testPlugin jarexec-testDefaultJarExecution | Memory: 3M/4M +----------------------------------------    multiproject:goal: build:start:    testPlugin: clean:clean:     [delete] Deleting directory C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target    clean:        [mkdir] Created dir: C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target java:prepare-filesystem:     [mkdir] Created dir: C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target\classes    java:compile:     [echo] Compiling to C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution/target/classes     [javac] Compiling 1 source file to C:\dev\mavenbook\code\plugins\jarexec\src\ plugin-test\testDefaultJarExecution\target\classes    java:jar-resources:    test:prepare-filesystem:     [mkdir] Created dir: C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target\test-classes     [mkdir] Created dir: C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target\test-reports    test:test-resources:    test:compile:     [echo] No test source files to compile.    test:test:     [echo] No tests to run.    jar:jar:     [jar] Building jar: C:\dev\mavenbook\code\plugins\jarexec\src\plugin-test\ testDefaultJarExecution\target\jarexec-testDefaultJa rExecution-1.0.jar    jarexec:run:     [java] It works...    [...] BUILD SUCCESSFUL Total time: 11 seconds

6.3.2. What just happened?

You have learned how to automate testing for the plug-ins you write. You used the ant:record tag to record the output of the program's execution. ant:record takes the output of a program and saves it to a log.txt file which is then tested using the assert tag library. The assert tag library is used to see if log.txt contains the output expected from the execution of the test application.

6.3.3. What about...

...if I make a mistake while writing the plug-in and I get some cryptic error when running the plugin:test goal?

Yes, you have found one limitation of the Multiproject project: it does not provide perfect error reporting! It is possible to get the following cryptic error message:

BUILD FAILED File...... C:\Documents and Settings\Vincent Massol\.maven\cache\ maven-plugin-plugin-1.6-SNAPSHOT\plugin.jelly Element... maven:maven Line...... 306 Column.... 34 Unable to obtain goal [testPlugin] -- C:\Documents and Settings\Vincent Massol\.maven\ cache\maven-multiproject-plugin-1.3.1\plugin .jelly:217:9: <maven:reactor> Reactor subproject failure occurred

The solution is to ask Maven to generate a stack trace (maven plugin:test -e), as you learned in Section 1.1. Then the real error will appear in the stack trace. Another possibility is to go into your test project and type maven testPlugin (or simply maven if you have set the default goal to be testPlugin). Fix the problem and then try executing the tests again from the top level with the plugin:test goal.



Maven. A Developer's Notebook
Maven: A Developers Notebook (Developers Notebooks)
ISBN: 0596007507
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net