开发者

How can I use maven and jUnit tests together?

开发者 https://www.devze.com 2023-02-01 06:40 出处:网络
I have a gwt application built in Maven, now I tried to run a simple GWT test like bellow: public class GwtTestLaughter extends GWTTestCase {

I have a gwt application built in Maven, now I tried to run a simple GWT test like bellow:

public class GwtTestLaughter extends GWTTestCase {

  /**
   * Specifies a module to use when running this test case. The returned
   * module must include the source for this class.
   * 
   * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
   */
    @Override
    public String getModuleName() {
        return "com.sample.services.joker.laughter.Laughter";
    }

    /**
     * Add as many tests as you like
     */
    public void testSimple() {
        assertTrue(true);
    }
}

and in the pom.xml file, configured the gwt-maven-plugin and maven-surefire-plugin as bellow:

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>gwt-maven-plugin</artifactId>
    <version>2.1.0-1</version>
    <configuration>
      <!-- Use the 'war' directory for GWT hosted mode -->
      <output>${basedir}/war</output>
      <webXml>${basedir}/war/WEB-INF/web.xml</webXml>
      <runTarget>index.html</runTarget>
      <!-- Make sure the GWT compiler uses Xerces -->
  <extraJvmArgs>
    -Dgwt.style=DETAILED -Xmx512M -Xss1024k -XX:MaxPermSize=128m -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl -Dlogback.configurationFile=./src/test/resources/logback-test.xml
  </extraJvmArgs>
</configuration>
<executions>
  <execution>
    <goals>
      <goal>compile</goal>
      <goal>test</goal>
    </goals>
  </execution>
</ex开发者_运维技巧ecutions>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
       <useFile>false</useFile>
       <forkMode>once</forkMode>
       <argLine>-Xmx128m</argLine>
       <systemPropertyVariable>
        <property>
          <name>log4j.configuration</name>
          <value>log4j.properties</value>
        </property>
       </systemPropertyVariables>
    </configuration>
    <executions>
       <execution>
          <id>unit-test</id>
          <phase>test</phase>
          <goals>
             <goal>test</goal>
          </goals>
          <configuration>
              <skip>false</skip>
              <includes>
                 <include>**/*Test.java</include>
              <includes>
              <excludes>
                 <exclude>**/GwtTest*.java</exclude>
              </excludes>
          </configuration>
        </execution>
   <execution>
      <id>integration-test</id>
      <phase>integration-test</phase>
      <goals>
         <goal>test</goal>
      </goals>
      <configuration>
          <skip>true</skip>
          <includes>
             <include>**/GwtTest*.java</include>
          <includes>
          <excludes>
             <exclude>**/*Test.java</exclude>
          </excludes>
      </configuration>
    </execution>
    <executions>
  </plugin>

When I ran 'mvn test' in command line, I can see only normal Junit tests ran(the one with Test.java file name), when i ran 'mvn integration-test', I still see all the tests, including normal Junit test and Gwt test(the ones with GwtTest.java file name) ran.

Question 1:

How can I totally exclude running normal Junit test during for integration test? or that's impossible? Because in default maven lifecycle, test phase is define to exist before integration-test, there is no way to skip the test phase to run a pure integration-test?

Since I mingled all the tests code under /src/test/java folder, when I ran 'mvn integration-test' and observed the output in command line window, I saw the following:

[INFO] running com.sample.services.joker.laughter.client.GwtTestLaughter 
..
[INFO] Validating newly compiled units
[INFO]    [ERROR] Errors in 'file:...src/test/java/com/sample/joker/laughter/client/file1Test.java'..
[INFO]    [ERROR] Line 42: No source code is available for type...; did you forget to inherit a required module?
...

Question 2:

I don't understand this, the gwt test is a very simple one,why it would validate a unrelated *Test.java and search for its source code. though eventually build successful with test passed, how can I get rid of those nasty error message?

Maybe I should forget about the gwt-mavin-plugin and stick with the classic Juint tests?


Hi I understand your problem and the probable solution lies on this gwt-maven-plugin documentation page: https://gwt-maven-plugin.github.io/gwt-maven-plugin/user-guide/testing.html

As per the plugin docs:

By intention: The 'test' goal is bound by defaults to integration-test phase and the GWTTestCase is not considered as a unit test as they require the whole GWT Module to run.

To run both Surefire and gwt-maven-plugin based tests (for regular server side JUnit tests with Surefire, and for client model and controller tests with GWT) you need to distinguish these tests from each other. This is done using a naming convention.

You can configure the Surefire plugin (responsible for running tests during maven build) to skip the GwtTests using some naming patterns .

A simpler way to separate classic and GWT tests is to name latests GwtTest"Something".java. As surefire looks for tests that are named Something"Test".java by default, they will be ignored during test phase.

By default, the gwt-maven-plugin uses GwtTest*.java as inclusion pattern so that such tests will not match the standard Surefire pattern. Using this convention you don't have to change your configuration.


You should add src files into classpath like this :

<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
  <additionalClasspathElements>
    <additionalClasspathElement>
       ${project.build.sourceDirectory}
    </additionalClasspathElement>
    <additionalClasspathElement>
       ${project.build.testSourceDirectory}
    </additionalClasspathElement>
  </additionalClasspathElements>
  <useManifestOnlyJar>false</useManifestOnlyJar>
  <forkMode>always</forkMode>
  <systemProperties>
    <property>
      <name>gwt.args</name>
      <value>-out \${webAppDirectory}</value>
    </property>
  </systemProperties>
</configuration>

Reference


I can help with question 1. To skip running tests:

mvn (goals) -Dmaven.test.skip=true

This will make it ignore JUnit tests.

As for question 2, classic JUnit may be the way to go. I'm not too familiar with GWT, but does it have test annotations (@test)? And what is on line 42 that is erroring?


Just an aside for you, in most of the non-trivial projects that I've been involved with, there is an extreme prejudice towards JUnit for two reasons. The first is that GWTUnit requires a spin up of the javascript context which is slow, painfully slow, compared to a JUnit test. Second, there really shouldn't be too much that you're writing that requires a Javascript context to test based on your design and code structure; primarily because of problem 1, but also remember that you are writing something with a GWT view right now, but you really want that to be agnostic of the view technology as much as possible. That way when Swing makes it's triumphant return to eminence, you can much more easily port it over. I'm kidding, a more likely scenario would be porting to Android or who knows what else in the future.

So basically, GWTUnit is very slow to run because of the environment it has to spin up, and in all reality, you should be (IMHO) factoring out your business logic so that you aren't eternally coupled to any one view rendering technology. In my opinion most of your logic that can be separated out from the pure UI world of widgets and panels should be, whether it's control flow type logic, validation logic, or anything other than just putting things on the screen and getting values into and out of them. Everything else should be out of those classes in a larger project, and take objects as inputs that have no tie to GWT in any way. If you do that you can JUnit the vast majority of your application, which is ridiculously fast, and you won't have to wait forever (in a large project heavy coverage with GWTUnit would take hours, maybe days). I won't go on about how great a strong unit test covered codebase is to maintain.

This rant is predicated by the last task I did here at my current job, there was a set of business logic that was wound up with the view layer that had (at the end of the unwinding and building up of a full unit test suite) 178 different scenarios that all had to execute properly. This was something that never should have known that it was running in GWT, but it was short cutted and was riddled with references to the view technology classes. In fact, this was something that was already written for an earlier version of the software and hadn't changed much, but they wrapped the logic up in that view layer(which was Swing). The new team has just repeated the sins of the earlier team, and because of that this code section required hours of testing by hand, which I'm sure didn't 100% cover the scenarios, as opposed to a quick several second unit test that runs them all.

0

精彩评论

暂无评论...
验证码 换一张
取 消