How to have the Maven build wait for the Jetty server to start in forked mode before running the integration tests?

孤街醉人 提交于 2019-12-03 22:08:40

问题


I have a report for the code coverage by the integration test.

I do have integration tests, and these are run successfully in the Maven build.

When I click on the "Sessions" link in the top right corner of the HTML report I can see my test classes in the list, but I cannot see my main classes that are exercised by the tests now, and all coverage report percentages are at zero.

As a side note, my unit test coverage works fine, with the percentages being displayed all right.

My configuration looks like:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18.1</version>
    <configuration>
      <argLine>${surefireArgLine}</argLine>
      <excludes>
        <exclude>**/integrationtest/*.java</exclude>
      </excludes>
    </configuration>
  </plugin>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.18.1</version>
     <configuration>
       <argLine>${failsafeArgLine}</argLine>
       <skipTests>${skipIntegrationTests}</skipTests>
      <includes>
        <include>**/integrationtest/*.java</include>
      </includes>
    </configuration>
    <executions>
      <execution>
        <id>integration-test</id>
        <goals>
          <goal>integration-test</goal>
        </goals>
      </execution>
      <execution>
        <id>verify</id>
        <goals>
          <goal>verify</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.5.201505241946</version>
    <executions>
      <execution>
        <id>pre-unit-test</id>
        <goals>
          <goal>prepare-agent</goal>
        </goals>
        <configuration>
          <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
          <propertyName>surefireArgLine</propertyName>
        </configuration>
      </execution>
      <execution>
        <id>post-unit-test</id>
        <phase>test</phase>
        <goals>
          <goal>report</goal>
        </goals>
        <configuration>
          <dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
          <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
        </configuration>
      </execution>
      <execution>
        <id>pre-integration-test</id>
        <phase>pre-integration-test</phase>
        <goals>
          <goal>prepare-agent-integration</goal>
        </goals>
        <configuration>
          <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
          <propertyName>failsafeArgLine</propertyName>
        </configuration>
      </execution>
      <execution>
        <id>post-integration-test</id>
        <phase>post-integration-test</phase>
        <goals>
          <goal>report-integration</goal>
        </goals>
        <configuration>
          <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
          <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.2.2.v20140723</version>
    <configuration>
      <httpConnector>
        <port>${jetty.port}</port>
      </httpConnector>
      <scanIntervalSeconds>10</scanIntervalSeconds>
      <stopPort>8805</stopPort>
      <stopKey>STOP</stopKey>
    </configuration>
    <executions>
      <execution>
        <id>start-jetty</id>
        <phase>pre-integration-test</phase>
        <goals>
          <goal>stop</goal> <!-- stop any stray process that has been running since before -->
          <goal>run-forked</goal>
        </goals>
        <configuration>
          <scanIntervalSeconds>0</scanIntervalSeconds>
          <daemon>true</daemon>
          <waitForChild>false</waitForChild>
          <maxStartupLines>200</maxStartupLines>
          <jvmArgs>${failsafeArgLine} -Djetty.port=${jetty.port}</jvmArgs>
        </configuration>
      </execution>
      <execution>
        <id>stop-jetty</id>
        <phase>post-integration-test</phase>
        <goals>
          <goal>stop</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Notice how the JaCoCo plugin is defined before the jetty one.

The console log shows a log of failed connection attempts. The integration tests cannot connect to the localhost. That is because the Jetty server hasn't had the time to start before Maven ran the tests.

org.apache.http.conn.HttpHostConnectException: Connection to http://localhost:8888 refused

Here is also another console log bit:

[STDERR] 2015-12-21 09:49:43.486:WARN:oejuc.AbstractLifeCycle:main: FAILED ServerConnector@2cd9b65d{HTTP/1.1}{0.0.0.0:8080}: java.net.BindExcep
tion: Address already in use
[STDERR] java.net.BindException: Address already in use
[STDERR]        at sun.nio.ch.Net.bind0(Native Method)
[STDERR]        at sun.nio.ch.Net.bind(Net.java:436)
[STDERR]        at sun.nio.ch.Net.bind(Net.java:428)
[STDERR]        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
[STDERR]        at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
[STDERR]        at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:277)
[STDERR]        at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
[STDERR]        at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:216)
[STDERR]        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
[STDERR]        at org.eclipse.jetty.maven.plugin.MavenServerConnector.doStart(MavenServerConnector.java:120)
[STDERR]        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
[STDERR]        at org.eclipse.jetty.server.Server.doStart(Server.java:359)
[STDERR]        at org.eclipse.jetty.maven.plugin.JettyServer.doStart(JettyServer.java:76)
[STDERR]        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
[STDERR]        at org.eclipse.jetty.maven.plugin.Starter.run(Starter.java:401)
[STDERR]        at org.eclipse.jetty.maven.plugin.Starter.main(Starter.java:516)
[STDERR] 2015-12-21 09:49:43.486:WARN:oejuc.AbstractLifeCycle:main: FAILED org.eclipse.jetty.maven.plugin.MavenServerConnector@630b8061: java.net.BindException: Address already in use
[STDERR] java.net.BindException: Address already in use
[STDERR]        at sun.nio.ch.Net.bind0(Native Method)
[STDERR]        at sun.nio.ch.Net.bind(Net.java:436)

Having the start value instead of the run-forked for the goal has the tests run fine. But I need to have it as run-forked for the code coverage report.

Using the <waitForChild>false</waitForChild> option changed nothing to the issue.

How to have the Maven build wait for the Jetty server to start in forked mode before running the integration tests ?

UPDATE: I could have the Maven build wait for the Jetty server to start in fork mode with the following <maxStartupLines>200</maxStartupLines> option.

But now, none of my integration tests, although they are run fine, are seen in the report.

My log says:

[INFO] --- jacoco-maven-plugin:0.7.5.201505241946:prepare-agent-integration (pre-integration-test) @ rest ---
[INFO] failsafeArgLine set to -javaagent:/home/stephane/.m2/repository/org/jacoco/org.jacoco.agent/0.7.5.201505241946/org.jacoco.agent-0.7.5.201505241946-runtime.jar=destfile=/home/stephane/source/...-rest/rest/target/coverage-reports/jacoco-it.exec

[INFO] <<< jetty-maven-plugin:9.2.2.v20140723:run-forked (start-jetty) @ rest <<<
[INFO] 
[INFO] --- jetty-maven-plugin:9.2.2.v20140723:run-forked (start-jetty) @ rest ---
[INFO] Configuring Jetty for project: Rest
[INFO] webAppSourceDirectory not set. Trying src/main/webapp
[INFO] Reload Mechanic: automatic
[INFO] Classes = /home/stephane/source/...-rest/rest/target/classes
[INFO] Context path = /
[INFO] Tmp directory = /home/stephane/source/...-rest/rest/target/tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] web.xml file = file:/home/stephane/source/...-rest/rest/src/main/webapp/WEB-INF/web.xml
[INFO] Webapp directory = /home/stephane/source/...-rest/rest/src/main/webapp

[INFO] Forked process starting
[INFO] Forked process started.

UPDATE: If I run the Maven command mvn jacoco:report-integration the console complains with a missing data file:

[INFO] --- jacoco-maven-plugin:0.7.5.201505241946:report-integration (default-cli) @ rest ---
[INFO] Skipping JaCoCo execution due to missing execution data file:/home/stephane/source/...-rest/rest/target/jacoco-it.exec

Indeed the data file is specified in the pom.xml file as being <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>

Why is it looked up as jacoco-it.exec instead of coverage-reports/jacoco-it.exec ?

Is it because the JaCoCo report is generated before the Jetty server has had time to stop and produce the data file ? But why the different file path then ? And how to tell the JaCoCo report to wait for it ?

UPDATE: I added a stopWait of 1 to the stop goal of the integration test:

  <execution>
    <id>stop-jetty</id>
    <phase>post-integration-test</phase>
    <goals>
      <goal>stop</goal>
    </goals>
    <configuration>
      <stopWait>1</stopWait>
    </configuration>
  </execution>

But it changed nothing to the issue.

UPDATE: Running the build with the -X option showed the following:

[INFO] 
[INFO] --- jacoco-maven-plugin:0.7.5.201505241946:report-integration (post-integration-test) @ rest ---
[DEBUG] Configuring mojo org.jacoco:jacoco-maven-plugin:0.7.5.201505241946:report-integration from plugin realm ClassRealm[plugin>org.jacoco:ja
coco-maven-plugin:0.7.5.201505241946, parent: sun.misc.Launcher$AppClassLoader@5c647e05]
[DEBUG] Configuring mojo 'org.jacoco:jacoco-maven-plugin:0.7.5.201505241946:report-integration' with basic configurator -->
[DEBUG]   (f) dataFile = /home/stephane/source/...-rest/rest/target/coverage-reports/jacoco-it.exec
[DEBUG]   (f) outputDirectory = /home/stephane/source/...-rest/rest/target/site/jacoco-it
[DEBUG]   (f) outputEncoding = UTF-8
[DEBUG]   (f) project = MavenProject: no.....db:rest:1.40.0-SNAPSHOT @ /home/stephane/source/...-rest/rest/pom.xml
[DEBUG]   (f) skip = false
[DEBUG]   (f) sourceEncoding = UTF-8
[DEBUG] -- end configuration --
[INFO] Analyzed bundle 'Rest' with 50 classes
[INFO] 
[INFO] --- jetty-maven-plugin:9.2.2.v20140723:stop (stop-jetty) @ rest ---
[DEBUG] Configuring mojo org.eclipse.jetty:jetty-maven-plugin:9.2.2.v20140723:stop from plugin realm ClassRealm[plugin>org.eclipse.jetty:jetty-maven-plugin:9.2.2.v20140723, parent: sun.misc.Launcher$AppClassLoader@5c647e05]
[DEBUG] Configuring mojo 'org.eclipse.jetty:jetty-maven-plugin:9.2.2.v20140723:stop' with basic configurator -->
[DEBUG]   (s) stopKey = STOP
[DEBUG]   (s) stopPort = 8805
[DEBUG]   (f) stopWait = 1
[DEBUG] -- end configuration --
[INFO] Waiting 1 seconds for jetty to stop
[INFO] Server reports itself as stopped

This tells me the report is being produced before the Jetty server has stopped. If that is the case, then it is faulty. How to have the report produced after the Jetty server stops ?


回答1:


After reading a bit about the plugin on http://eclemma.org/jacoco/trunk/doc/report-integration-mojo.html I noticed that it said:

Binds by default to the lifecycle phase: verify.

So, change to:

    <execution>
        <id>post-integration-test</id>
        <phase>verify</phase>
        <goals>
          <goal>report-integration</goal>
        </goals>
        <configuration>
          <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
          <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
        </configuration>
    </execution>

(or just leave out the phase) and it should work.



来源:https://stackoverflow.com/questions/34343214/how-to-have-the-maven-build-wait-for-the-jetty-server-to-start-in-forked-mode-be

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!