在项目的RCP程序中有两类代码需要测试:
- 一类是testSourceDirectory里的测试代码,由maven-surefire-plugin执行。
- 一类是单独的test plugin里的测试代码,由tycho-surefire-plugin执行。
1. 测试testSourceDirectory
testSourceDirectory默认是src/test/java,可以在pom中修改,Eclipse plugin project的源代码在src folder里,对应的测试代码通常就放在test folder里。pom文件设置:
<build> <sourceDirectory>src</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> </build>
对于packaging类型为eclipse-plugin,eclipse-test-plugin等tycho类型的Mave项目,需要明白以下两点:
- Maven使用tycho-compiler-plugin编译plugin,tycho-compiler-plugin没有testCompile goal,所以testSourceDirectory里的代码不会被编译。
- maven-compiler-plugin有testCompile goal,但是effective pom里没有,默认不会执行。
所以为了能够测试testSourceDirectory,我们需要添加maven-compiler-plugin来编译测试代码,然后使用maven-surefire-plugin运行unit test。务必写明在哪个phase执行哪个goal,effective pom里默认没有,所以不会继承任何<execution/>设置。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <executions> <execution> <id>compiletests</id> <phase>test-compile</phase> <goals> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <executions> <execution> <id>test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin>
2. 测试单独的test plugin
test plugin是运行在OSGI环境中的,会先加载其所依赖的plugin,然后执行本身的unit test,如果有UI的话,会打开相应的UI。
2.1 设置Target Platform
添加一个target platform plugin,在Eclipse中作为我们的开发、运行环境,在Maven中作为我们的运行环境。
Eclipse Plugin-in Development Environment这个非常重要,plugin test依赖的junit和junit runtime包含在这个feature里面。
2.2 配置POM
在pom中聚合这个target platform plugin,并且使用target-platorm-configuration插件配置maven在构建过程中使用该target platform。
<modules> <module>../tychodemo.target</module> </modules> <build> <plugins> <plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>target-platform-configuration</artifactId> <version>${tycho-version}</version> <configuration> <target> <artifact> <groupId>tychodemo</groupId> <artifactId>tychodemo.target</artifactId> <version>0.0.1-SNAPSHOT</version> </artifact> </target> <environments> <!-- Specify environment value according to system type --> <environment> <os>macosx</os> <ws>cocoa</ws> <arch>x86_64</arch> </environment> <!-- <environment> <os>win32</os> <ws>win32</ws> <arch>x86_64</arch> </environment> <environment> <os>linux</os> <ws>gtk</ws> <arch>x86_64</arch> </environment> --> </environments> </configuration> </plugin> </plugins> </build>
tycho-surefire-plugin的配置:
- <useUIHarness/>为false,表示使用headless mode运行,即使没有Display也可以运行;
- <useUIThread/>为true,表示使用UI线程。
- <providerHint/>为junit4,表示使用junit4执行unit test。Indigo只支持junit3,即使写成junit4,junit4的unit test也不会被执行。
<plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>tycho-surefire-plugin</artifactId> <version>${tycho-version}</version> <configuration> <useUIHarness>false</useUIHarness> <useUIThread>true</useUIThread> <providerHint>junit4</providerHint> </configuration> </plugin>
2.3 给test plugin添加依赖
test plugin运行在OSGI环境中,dependencies中添加:
- org.junit:只能是RCP environment自己的junit。手动在class path中添加一个junit,或者使用自己封装的third-party plugin里的junit,都不work。运行时说,cannot specify target Test Framework, available is junit3, junit4, junit47, junit5。这句英文是我凭记忆写的,原message应该不是这样的。这个错误,就算在tycho-surefire-plugin里指定Test Framework也不work。
- org.eclipse.jdt.junit.runtime:这个plugin也是RCP environment里的,用于发现和执行测试类。如果没有这个依赖,一个测试也不会执行,最后说no test is found。
2.4 编写测试代码
Test plugin中的测试代码,要放在src folder里,不能放在test folder里,因为tycho-surefire-plugin只会在src folder里寻找test classes。当然我们也可以在test folder里写测试测试类,但这些测试类只能被maven-surefire-plugin执行(前提是配置了maven-surefire-plugin)。
Plug-in test中,可以访问UI。也就是可以测试UI,例如测试当前OSGI环境中某个Service是否注册了;打开一个UI,检测各个Widget是否正确等。
注意:在Eclipse Indigo 3.7.2环境中,plugin unit test要使用Junit 3的写法,继承TestCase类。Junit 4的annotation写法,经过测试,Eclipse上执行class loader抛异常;maven命令行执行,无法识别这些测试类。
Example:
public class HelloPlutinTest extends TestCase { public void testShellExist() { assertNotNull(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); } }
2.5 运行plugin test
Eclipse上执行:右键 —> Run As / Debug As —> Junit Plug-in Test。
Maven命令行执行:tycho-surefire-plugin绑定在integration-test phase上,执行mvn integration-test便可。
3. 总结
如果项目中的Junit Plug-in Test不测UI,它就跟普通的Junit测试没啥两样,但是性能不如普通的Junit测试,因为Junit Plugin-in Test要初始化运行环境,加载需要的plugin等。
unit test的执行要尽可能的快,所以如果Junit Plug-in Test里面没有测试UI的类,我倾向于使用maven-surefire-plugin来执行。
小技巧:将Junit Plugin-in Test工程的source folder从src改为test,它们就会变被maven-surefire-plugin执行,而tycho-surefire-plugin就不会执行它们。