使用Maven对Eclipse RCP程序测试

By | 2019年7月9日

在项目的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项目,需要明白以下两点:

  1. Maven使用tycho-compiler-plugin编译plugin,tycho-compiler-plugin没有testCompile goal,所以testSourceDirectory里的代码不会被编译。
  2. 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里面。

屏幕快照 2019 07 09 下午10 04 44

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。

屏幕快照 2019 07 09 下午10 07 06

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就不会执行它们。