Maven Failsafeプラグインを使って、結合テストを自動化

[Maven Failsafe Plugin] (https://maven.apache.org/surefire/maven-failsafe-plugin/)を利用すると結合テストを自動化できることが分かったため、備忘録として記載する。

例えば、下記のようなテストを自動化したい場合に使える
--
- サーブレット、フィルターにてレスポンス情報を作成するアプリケーションに対して、リクエストを投げ、想定通りのレスポンスが返却されることを確認する。

サンプルプログラム
--

環境
--
- Apache Tomcat
- JUnit

アプリケーションの実装
--
- 下記MavenアーキタイプにてMavenプロジェクトを作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/301697/1137f49c-e146-ae78-dcf2-bd508e897db7.png)

- 下記の形で依存関係を定義

```xml:pom.xml
	<dependencies>
		<!-- Servlet API -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<!-- クライアント -->
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-client</artifactId>
			<version>2.28</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.inject</groupId>
			<artifactId>jersey-hk2</artifactId>
			<version>2.28</version>
			<scope>test</scope>
		</dependency>
		<!-- JUnit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
```

- 下記ソースコードを用意

```java:DemoServlet.java
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/demo")
public class DemoServlet extends HttpServlet {

	private static final long serialVersionUID = 2564544155028547344L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.getWriter().println("body");
	}
}

```

```java:DemoFilter.java
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

@WebFilter("/demo")
public class DemoFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
		wrapper.setHeader("Header-Name", "value");
		chain.doFilter(request, wrapper);
	}

	@Override
	public void destroy() {
	}
}
```

- 下記テストコードを用意

```java:DemoIT.java
import static org.junit.Assert.assertEquals;

import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;

import org.junit.Test;

public class DemoIT {

	@Test
	public void test() {
		// サーバーへリクエスト送信
		Response response = ClientBuilder.newClient().target("http://localhost:8080/sample-it/demo").request().get();
		// フィルターが想定通り動作していることを確認
		assertEquals("value", response.getHeaderString("Header-Name"));
		// サーブレットが想定通り動作していることを確認
		assertEquals("body", response.readEntity(String.class).trim());
	}
}
```

Failsafeプラグインを定義
--

あとは、

- アプリケーションサーバーを起動
- サーバーへアプリケーションをデプロイ
- テストクラスを実行
- アプリケーションサーバーを停止

の流れで処理を自動実行させるようにする。

そのために、Failsafeプラグインを利用する。
（Failsafeプラグインはテスト実行を制御できるプラグイン。上記のようにテスト実行の前処理や後処理を定義することができる。）
サーバーの起動・アプリケーションのデプロイは、Failsafeプラグインではできないため、
[Apache Tomcat Maven plugin] (http://tomcat.apache.org/maven-plugin-2.1/tomcat7-maven-plugin/plugin-info.html)を利用。
以下が設定。

```xml:pom.xml
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-failsafe-plugin</artifactId>
				<version>3.0.0-M3</version>
				<executions>
					<execution>
						<goals>
							<goal>integration-test</goal>
							<goal>verify</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<!-- Tomcat操作用プラグイン -->
			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<executions>
					<!-- テスト実行前処理 -->
					<execution>
						<id>run</id>
						<phase>pre-integration-test</phase>
						<goals>
							<!-- Tomcat起動・アプリケーションのデプロイ -->
							<goal>run</goal>
						</goals>
						<!-- run以降のゴールが実行できるようにするための設定 -->
						<configuration>
							<fork>true</fork>
						</configuration>
					</execution>
					<!-- テスト実行後処理 -->
					<execution>
						<id>shutdown</id>
						<phase>post-integration-test</phase>
						<goals>
							<!-- Tomcat停止 -->
							<goal>shutdown</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
```

テストは下記コマンドを実行すれば行うことができる。

```
mvn clean verify
```

Spring Boot系はSprintBootTestを使えば、結合テストも自動化できそうなのでFailsafeプラグインを利用する価値はないかもしれない。ただし、Spring MVCなどサーバーにデプロイしないといけないアプリケーションの場合は、本プラグインを用いれば自動化することができる。アジャイルなど仕様変更が多く発生する場合は使えそう。