`

Integration Testing with HTTP, HTTPS and Maven

阅读更多

Earlier this week, I was tasked with getting automated integration tests working in my project at Overstock.com. By automated, I mean that ability to run "mvn install" and have the following process cycled through:

 

Start a container

Deploy the application

Run all integration tests

Stop the container

Since it makes sense for integration tests to run in Maven's integration-test phase, I first configured the maven-surefire-plugin to skip tests in the test phase and execute them in the integration-test phase. I used the <id>default-phase</id> syntax to override the plugins' usual behavior.

<plugin>

  <artifactId>maven-surefire-plugin</artifactId>

  <executions>

    <execution>

      <id>default-test</id>

      <configuration>

        <excludes>

          <exclude>**/*Test*.java</exclude>

        </excludes>

      </configuration>

    </execution>

    <execution>

      <id>default-integration-test</id>

      <phase>integration-test</phase>

      <goals>

        <goal>test</goal>

      </goals>

      <configuration>

        <includes>

          <include>**/*Test.java</include>

        </includes>

        <excludes>

          <exclude>none</exclude>

          <exclude>**/TestCase.java</exclude>

        </excludes>

      </configuration>

    </execution>

  </executions>

</plugin>

After I had this working, I moved onto getting the container started and stopped properly. In the past, I've done this using Cargo and it's always worked well for me. Apart from the usual setup I use in AppFuse archetypes (example pom.xml), I added a couple additional items:

 

Added <timeout>180000</timeout> so the container would wait up to 3 minutes for the WAR to deploy.

In configuration/properties, specified <context.path>ROOT</context.path> so the app would deploy at the / context path.

In configuration/properties, specified <cargo.protocol>https</cargo.protocol> since many existing unit tests made requests to secure resources.

I started by using Cargo with Tomcat and had to create certificate keystore in order to get Tomcat to start with SSL enabled. After getting it to start, I found the tests failed with the following errors in the logs:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 

unable to find valid certification path to requested target

at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)

 

Co-workers told me this was easily solved by adding my 'untrusted' cert to my JVM keystore. Once all this was working, I thought I was good to go, but found that some tests were still failing. The failures turned out to be because they were talking to http and https was the only protocol enabled. After doing some research, I discovered that Cargo doesn't support starting on both http and https ports.

 

So back to the drawing board I went. I ended up turning to the maven-jetty-plugin and the tomcat-maven-plugin to get the functionality I was looking for. I also automated the certificate keystore generation using the keytool-maven-plugin. Below is the extremely-verbose 95-line profiles section of my pom.xml that allows either container to be used.

 

Sidenote: I wonder how this same setup would look using Gradle?

 

<profiles>

  <profile>

    <id>jetty</id>

    <activation>

      <activeByDefault>true</activeByDefault>

    </activation>

    <build>

      <plugins>

        <plugin>

          <groupId>org.mortbay.jetty</groupId>

          <artifactId>maven-jetty-plugin</artifactId>

          <version>6.1.26</version>

          <configuration>

            <contextPath>/</contextPath>

            <connectors>

              <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">

                <!-- forwarded == true interprets x-forwarded-* headers -->

                <!-- http://docs.codehaus.org/display/JETTY/Configuring+mod_proxy -->

                <forwarded>true</forwarded>

                <port>8080</port>

                <maxIdleTime>60000</maxIdleTime>

              </connector>

              <connector implementation="org.mortbay.jetty.security.SslSocketConnector">

                <forwarded>true</forwarded>

                <port>8443</port>

                <maxIdleTime>60000</maxIdleTime>

                <keystore>${project.build.directory}/ssl.keystore</keystore>

                <password>overstock</password>

                <keyPassword>overstock</keyPassword>

              </connector>

            </connectors>

            <stopKey>overstock</stopKey>

            <stopPort>9999</stopPort>

          </configuration>

          <executions>

            <execution>

              <id>start-jetty</id>

              <phase>pre-integration-test</phase>

              <goals>

                <goal>run-war</goal>

              </goals>

              <configuration>

                <daemon>true</daemon>

              </configuration>

            </execution>

            <execution>

              <id>stop-jetty</id>

              <phase>post-integration-test</phase>

              <goals>

                <goal>stop</goal>

              </goals>

            </execution>

          </executions>

        </plugin>

      </plugins>

    </build>

  </profile>

  <profile>

    <id>tomcat</id>

    <build>

      <plugins>

        <plugin>

          <groupId>org.codehaus.mojo</groupId>

          <artifactId>tomcat-maven-plugin</artifactId>

          <version>1.1</version>

          <configuration>

            <addContextWarDependencies>true</addContextWarDependencies>

            <fork>true</fork>

            <path>/</path>

            <port>8080</port>

            <httpsPort>8443</httpsPort>

            <keystoreFile>${project.build.directory}/ssl.keystore</keystoreFile>

            <keystorePass>overstock</keystorePass>

          </configuration>

          <executions>

            <execution>

              <id>start-tomcat</id>

              <phase>pre-integration-test</phase>

              <goals>

                <goal>run-war</goal>

              </goals>

            </execution>

            <execution>

              <id>stop-tomcat</id>

              <phase>post-integration-test</phase>

              <goals>

                <goal>shutdown</goal>

              </goals>

            </execution>

          </executions>

        </plugin>

      </plugins>

    </build>

  </profile>

</profiles>

 

With this setup in place, I was able to automate running our integration tests by simply typing "mvn install" (for Jetty) or "mvn install -Ptomcat" (for Tomcat). For running in Hudson, it's possible I'll have to further enhance things to randomize the port and pass that into tests as a system property. The build-helper-maven-plugin and its reserve-network-port goal is a nice way to do this. Note: if you want to run more than one instance of Tomcat at a time, you might have to randomize the ajp and rmi ports to avoid collisions.

 

The final thing I encountered was our app didn't shutdown gracefully. Luckily, this was fixed in a newer version of our core framework and upgrading fixed the problem. Here's the explanation from an architect on the core framework team.

 

The hanging problem was caused by the way the framework internally aggregated statistics related to database connection usage and page response times. The aggregation runs on a separate thread but not as a daemon thread. Previously, the aggregation threads weren't being terminated on shutdown so the JVM would hang waiting for them to finish. In the new frameworks, the aggregation threads are terminated on shutdown.

 

Hopefully this post helps you test your secure and unsecure applications at the same time. At the same time, I'm hoping it motivates the Cargo developers to add simultaneous http and https support. 

 

Update: In the comments, Ron Piterman recommended I use the Maven Failsafe Plugin because its designed to run integration tests while Surefire Plugin is for unit tests. I changed my configuration to the following and everything still passes. Thanks Ron!

 

<plugin>

  <artifactId>maven-surefire-plugin</artifactId>

  <version>2.7.2</version>

  <configuration>

    <skipTests>true</skipTests>

  </configuration>

</plugin>

<plugin>

  <artifactId>maven-failsafe-plugin</artifactId>

  <version>2.7.2</version>

  <configuration>

    <includes>

      <include>**/*Test.java</include>

    </includes>

    <excludes>

      <exclude>**/TestCase.java</exclude>

    </excludes>

  </configuration>

  <executions>

    <execution>

      <id>integration-test</id>

      <phase>integration-test</phase>

      <goals>

        <goal>integration-test</goal>

      </goals>

    </execution>

    <execution>

      <id>verify</id>

      <phase>verify</phase>

      <goals>

        <goal>verify</goal>

      </goals>

    </execution>

  </executions>

</plugin>

 

Update 2: In addition to application changes to solve hanging issues, I also had to change my Jetty Plugin configuration to use a different SSL connector implementation. This also required adding the jetty-sslengine dependency, which has been renamed to jetty-ssl for Jetty 7.

<connector implementation="org.mortbay.jetty.security.SslSelectChannelConnector">

...

<dependencies>

  <dependency>

    <groupId>org.mortbay.jetty</groupId>

    <artifactId>jetty-sslengine</artifactId>

    <version>6.1.26</version>

  </dependency>

</dependencies

转载:http://raibledesigns.com/rd/entry/integration_testing_with_http_https

分享到:
评论

相关推荐

    Android.Application.Development.with.Maven

    Title: Android Application Development with Maven Author: Patroklos Papapetrou Length: 175 pages Edition: 1 Language: English Publisher: Packt Publishing Publication Date: 2015-02-27 ISBN-10: ...

    Android.Application.Development.with.Maven.17

    Title: Android Application Development with Maven Author: Patroklos Papapetrou Length: 175 pages Edition: 1 Language: English Publisher: Packt Publishing Publication Date: 2015-02-27 ISBN-10: ...

    maven-and-osgi

    In terms of capabilities, Maven is an improvement to Apache Ant-thanks to numerous plug-ins and built-in integration with unit testing frameworks such as JUnit. Tired of writing the same build logic ...

    Implementing.Domain.Specific.Languages.with.Xtext.and.Xtend.2nd.Ed

    Build your Xtext DSLs easily with Maven/Tycho and Gradle; Write a code generator and an interpreter for a DSL; Explore the Xtext scoping mechanism for symbol resolution; Test most aspects of the DSL ...

    testing in scala

    Testing in Scala starts with an introduction of the Scala programming language, explains why project infrastructure is critical, and provides compelling reasons to use Scala testing frameworks to not ...

    Wrox.Press.Professional.Java.Tools.for.Extreme.Programming.eBook-LiB.part3

    They then explain how to automate the testing process using JUnit, Cactus, and other tools, and to enhance project management and continuous integration through Maven and AntHill. Finally, they show ...

    Wrox.Press.Professional.Java.Tools.for.Extreme.Programming.eBook-LiB.part4

    They then explain how to automate the testing process using JUnit, Cactus, and other tools, and to enhance project management and continuous integration through Maven and AntHill. Finally, they show ...

    Professional Java Tools for Extreme Programming (JAVA经典书籍英文版)_part2

    They then explain how to automate the testing process using JUnit, Cactus, and other tools, and to enhance project management and continuous integration through Maven and AntHill. Finally, they show ...

    Professional Java Tools for Extreme Programming (JAVA经典书籍英文版)_part1

    They then explain how to automate the testing process using JUnit, Cactus, and other tools, and to enhance project management and continuous integration through Maven and AntHill. Finally, they show ...

    Jenkins.Continuous.Integration.Cookbook.2nd.Edition

    You will then explore the relationship between Jenkins builds and Maven pom.xml. Then, you will learn how to use plugins to display code metrics and fail builds to improve quality, followed by how to...

    A.Practical.Guide.to.Continuous.Delivery.epub

    Implement build automation and continuous integration with Gradle, Maven, and Jenkins Perform static code reviews with SonarQube and repositories to store build artifacts Establish automated GUI and ...

    maven学习资料,通过这基本书可以很快上手,包含chm文档

    In terms of capabilities, Maven is an improvement to Apache Ant-thanks to numerous plug-ins and built-in integration with unit testing frameworks such as JUnit. Tired of writing the same build logic ...

    Mastering.Spring.Cloud

    Latency and fault tolerance with Hystrix Configuration management with Archaius Discovery and distributed configuration An alternative &#x2013; Consul Apache Zookeeper Miscellaneous projects ...

    Mastering.Gradle.178398136

    You will also get hands-on with building and testing projects using Gradle. You will then begin to cover diverse topics, such as Continuous Integration with Jenkins and TeamCity, Migration strategies...

    Gradle in Action

    Along the way, it touches on advanced topics like testing, continuous integration, and monitoring code quality. You’ll also explore tasks like setting up your target environment and deploying your ...

    mastering-spring-cloud2018

    with service discovery and create simple and more advanced routing and filtering rules. Chapter 9, Distributed Logging and Tracing, will introduce some popular tools for collecting and analizing ...

    thymeleaf-tests-3.0-spring5.zip

    Tests included cover expressions, standard dialect attributes, Spring integration and also most of the example applications, among other topics. Tests under the org.thymeleaf.engine package are ...

    Maven动作范围:Maven GitHub动作范围

    Maven行动范围GitHub用于自动运行使用进行测试的测试的操作。... undefinedlabs/scope-for-maven-action@v1 with : dsn : ${{secrets.SCOPE_DSN}} # required run-tests : true # optional - default is 'tr

    tractor-maven-plugin:Amazon Device Farm测试执行和结果管理Maven插件

    拖拉机Maven插件 Amazon Device Farm测试执行和结果管理Maven插件。 它通过上载应用程序和测试框架包来简化整个过程,然后执行测试并下载结果,包括视频,屏幕截图和自定义工件。 该项目支持所有框架类型,并允许...

Global site tag (gtag.js) - Google Analytics