GUIテストの自動化と結果の可視化

<!-- 公開用 -->

# GUIテストの自動化と結果の可視化

本稿では、GUIテストが実行し、その結果をキレイに可視化するような環境の構築法を紹介する。あくまで環境構築の手順のみ紹介し、各ライブラリの詳細な利用方法についての詳しい説明は省く。

Allureによるテスト結果の可視化は[こんな感じ](https://demo.qameta.io/allure/)。

## 対象者

- テスト自動化をしたことがない人
- テスト結果をグラフなどで可視化したい人
- Javaの知識がある人

## セットアップ環境

Windows10

# 必要なソフトウェアのインストールと設定

たくさんある。

## JDK8

Javaプログラムの開発に必要。Oracle製を使う。インストーラーでインストール。バージョンは執筆時の最新版を使用している。

[JDK8のダウンロードページ](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)

以下にインストール。

```txt
C:\Program Files\Java\jdk1.8.0_201
```

以下にPathを通す。

```txt
C:\Program Files\Java\jdk1.8.0_201\bin
```

環境変数`JAVA_HOME`を以下のように設定する。

```txt
C:\Program Files\Java\jdk1.8.0_201
```

ここまで出来たら以下のコマンドで確認。

```cmd:cmd
C:\>java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
```

## Maven

Java用のビルドツール。パッケージのダウンロードや依存性解決を自動で行ってくれる。以下のサイトからZIPをダウンロード。今回はバージョン`3.6.0`を使う。

[Mavenのダウンロードページ](https://maven.apache.org/download.cgi)

ダウンロード後、解凍したものを以下に配置。

```txt
C:\Program Files\apache-maven-3.6.0
```

以下にPathを通す。

```txt
C:\Program Files\apache-maven-3.6.0\bin
```

ここまで出来たら以下のコマンドで確認。

```cmd:cmd
c:\>mvn --version
c:\
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: C:\Program Files\apache-maven-3.6.0\bin\..
Java version: 1.8.0_201, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk1.8.0_201\jre
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
```

次にローカルリポジトリを設定する。ここにMavenがダウンロードしたパッケージが配置される。

まず、ローカルリポジトリ用のフォルダを作成する。

```cmd:cmd
c:\>mkdir "c:\Program Files\apache-maven-3.6.0\local-repository"
```

次に設定ファイル`C:\Program Files\apache-maven-3.6.0\conf\settings.xml`に以下を追記する。

```xml
<localRepository>C:\Program Files\apache-maven-3.6.0\local-repository</localRepository>
```

なお、デフォルトのローカルリポジトリは`${user.home}\.m2\repository`である。デフォルトのままでもいい。

プロキシ下で環境構築する場合はこの`settings.xml`にproxyの設定を必ず行う。

```xml
<proxies>
    <proxy>
      <id>http_proxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypasswd</password>
      <host>proxy.example.com</host>
      <port>8080</port>
    </proxy>
    <proxy>
      <id>https_proxy</id>
      <active>true</active>
      <protocol>https</protocol>
      <username>proxyuser</username>
      <password>proxypasswd</password>
      <host>proxy.example.com</host>
      <port>8080</port>
    </proxy>
  </proxies>
```

## Allure

テスト結果をグラフなどで可視化するツール。以下のサイトからZIPをダウンロード（"Links"->"Download"）。今回はバージョン`2.10.0`を使う。

[Allureのダウンロードページ](https://github.com/allure-framework/allure2/releases)

ダウンロード後、解凍したものを以下に配置。

```txt
C:\Program Files\allure-2.10.0
```

以下にPathを通す。

```txt
C:\Program Files\allure-2.10.0\bin
```

以下のコマンドで確認。

```cmd:cmd
c:\>allure --version
2.10.0
```

## IntelliJ IDEA

主にJavaの開発で使用するIDE。Community版を使う。以下のサイトからインストーラーをダウンロードして実行。

[IntelliJ IDEAのダウンロードページ](https://www.jetbrains.com/idea/download/)

ひとまず、以上でダウンロードは終わり。

# IntelliJでCucumberテストコード作成

Cucumberはテストを自然言語風に記述できるようにするフレームワークである。featureファイルにテストの流れを記述し、ステップ定義に実際の処理を書く。

まず、Cucumberを使って実際にテストを書いてみる。次に、Selenideを使ったGUIテストを書いてみる。

## プロジェクトの作成

左ペインで"Maven"を選択し、Nextをクリック。"Create from archetype"にはチェックを入れない。

<img width="552" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/279459/42a6a295-d26e-3d0d-2a41-4ec3f07b0ede.png">


以下のように設定し、Nextをクリック。ここの入力欄は何でもよい。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/279459/705e5918-8509-7fdf-de3c-e30f24ed49fd.png)

そのまま"Finish"をクリック。プロジェクトが作成される。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/279459/d2de2f30-b8e4-cc42-0449-93c9841c2b90.png)

## 文字コードの設定

"File"->"Settings"->"Editor"->"File Encodings"

- Global Encoding: UTF-8
- Project Encoding: ShiftJIS

Project EncodingはShiftJISにしないと、コンソールへの日本語出力が文字化けする。

<img width="719" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/279459/82b61059-e8c7-e058-6ec7-37044ad73b6a.png">

## フォントの設定

"File"->"Settings"->"Editor"->"Font"

日本語対応フォントを選ぶ。ここでは`Meiryo UI`を選択した。この設定をしないと日本語が文字化けする可能性がある。

<img width="666" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/279459/a1b246c3-07f3-247b-d9e7-6bedc46a4f19.png">

## Mavenの設定

"File"->"Settings"->"Maven"

先ほどインストールしたMavenの場所を"Maven home directory"に設定する。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/279459/9189b433-4591-9278-ff9f-4737a85e8c18.png)

## pom.xmlの編集

`pom.xml`を以下のようにする。`<properties>`と`<dependencies>`を追加する。

各パッケージのバージョンはそれぞれの依存関係を考慮して設定する。依存関係は例えば[ここ](https://mvnrepository.com/)で調べられる。

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>sandbox</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <!-- java8で書く -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <!-- 文字コードはUTF-8 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <!-- バージョン指定 -->
        <cucumber.version>4.2.5</cucumber.version>
        <selenide.version>5.1.0</selenide.version>
        <allure.version>2.10.0</allure.version>
        <junit.version>4.12</junit.version>
    </properties>

    <dependencies>
        <!-- Java用Cucumber -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- JUnitでCucumberを使うためのパッケージ -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Selenide -->
        <dependency>
            <groupId>com.codeborne</groupId>
            <artifactId>selenide</artifactId>
            <version>${selenide.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- AllureでCucumberテストをうまく出力するためのパッケージ -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-cucumber4-jvm</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- AllureでSelenideテストをうまく出力するためのパッケージ -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-selenide</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
```

追加したら、`autotest`プロジェクトを右クリック->"Maven"->"Reimport"

Mavenがパッケージのダウンロードを開始する。

![7.png](https://qiita-image-store.s3.amazonaws.com/0/279459/0e99425c-732f-3581-6e10-f5363adc77f3.png)

## Cucumberプラグインのインストール

IntelliJにCucumberプラグインをインストールすることによってfeatureファイルの編集が容易になる。

"File"->"Settings"->"Plugins"->"Marketplace"

検索窓に"Cucumber"を入力して"Cucumber for Java"を見つける。そのまま"Install"をクリック。終わったらIDEを再起動する。

<img width="653" alt="8.png" src="https://qiita-image-store.s3.amazonaws.com/0/279459/46224274-359a-b431-0dd3-456a80c892cc.png">

## featureファイルの追加

### featureファイルとは

featureファイルは機能ごとにテストの流れを記述するファイルである。自然言語風であり、非技術者でも読みやすい。[Gherkin](https://docs.cucumber.io/gherkin/reference/)という言語で記述される。なお、ここではGherkinの文法を解説しない。

featureファイルの例を以下に示す。この例では1つの`機能`に対して3つの`シナリオ`が存在する。ここではどのシナリオも4つの`ステップ`から成る。最後の`シナリオ`はテンプレート化されているため、テストケースは全部で5つとなる。

```gherkin:example.feature
#language: ja
  機能: ログイン

    @正常系
    シナリオ:ログインに成功する
      前提 ログインページにアクセスする
      もし 正しいIDを入力する
      かつ 正しいパスワードを入力する
      ならば ログインに成功する

    @異常系
    シナリオ: ログインに失敗する
      前提 ログインページにアクセスする
      もし 正しいIDを入力する
      かつ 間違ったパスワードを入力する
      ならば ログインに失敗する

    @正常系
    シナリオテンプレート: ログインAPI
      もし <id>のIDを設定する
      かつ <pass>のパスワードを設定する
      かつ API実行する
      ならば ログインに成功する

      サンプル:
      | id | pass|
      |"hoge"|"hogepass"|
      |"fuga"|"fugapass"|
      |"piyo"|"piyopass"|
```

### featureファイルの作成

`autotest\src\test\resources`に`動作試験.feature`を作成する（フォルダを右クリック->"New"->"File"）。`resources`フォルダがなければ作成する。内容は以下のようにする。

3つのステップから成るシナリオが1つだけ存在している。

```gherkin:動作試験.feature
# language: ja
機能: 動作確認
  シナリオ: テストシナリオ
    前提 ここは地球である
    もし 今日も日が昇る
    ならば 明日も日が昇る
```

## ステップ定義の追加

`autotest\src\test\java`に`Stepdefs.java`ファイルを作成する。内容は以下のようにする。

これは`動作試験.feature`で記述した3つのステップの実装である。

```java:Stepdefs.java
import cucumber.api.java.ja.ならば;
import cucumber.api.java.ja.もし;
import cucumber.api.java.ja.前提;

public class Stepdefs {
    @前提("ここは地球である")
    public void ここは地球である() {
        System.out.println("ここは水の星、地球である");
    }

    @もし("今日も日が昇る")
    public void 今日も日が昇る() {
        System.out.println("今日もいつものように日が昇る");
    }

    @ならば("明日も日が昇る")
    public void 明日も日が昇る() {
        System.out.println("望まずとも、明日も日が昇るだろう");
    }
}
```

ここでは簡単のため、標準出力するだけの実装とする。実際はアサーションコ―ドなどを記述する。

## エントリポイントの作成

JUnitテストとして実行するので、エントリポイントを作成する。`autotest\src\test\java`に`RunCucumberTest.java`ファイルを作成する。内容は以下。

```java:RunCucumberTest.java
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/resources", plugin = {"pretty"}, monochrome = true)
public class RunCucumberTest {
}
```

## Cucumberテストの実行

プロジェクトルート(`pom.xml`のあるディレクトリ)上で`mvn test`を実行。または右の"Maven"タブを展開して"test"をダブルクリックする。

<img width="807" alt="9.png" src="https://qiita-image-store.s3.amazonaws.com/0/279459/a3e7aeee-29b4-b72d-502d-1966daed2bdf.png">

実行結果は以下のようになる。

```txt
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running RunCucumberTest
ここは水の星、地球である
今日もいつものように日が昇る
望まずとも、明日も日が昇るだろう
機能: 動作確認

  シナリオ: テストシナリオ # src/test/resources/動作確認.feature:3
    前提ここは地球である  # Stepdefs.ここは地球である()
    もし今日も日が昇る   # Stepdefs.今日も日が昇る()
    ならば明日も日が昇る  # Stepdefs.明日も日が昇る()

1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.179s

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.531 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
```

# Selenideの導入

SelenideはGUIテストに特化したウェブブラウザ操作ライブラリである。Seleniumのラッパー。

今回はGoogleのページを開いて、検索機能を使うデモを書く。ブラウザはGoogle Chromeを使用する。

## Webdriverのダウンロード

ブラウザの操作にはWebDriverが必要である。以下よりChrome用をダウンロードする。インストールされているChromeのバージョンにあったものを選ぶ。

[ChromeのWebdriverのダウンロードページ](http://chromedriver.chromium.org/downloads)

ダウンロードしたら`chromedriver.exe`を、`autotest\driver`以下に配置。

Selenideのバージョンによっては、テスト実行時にWebDriverのダウンロードを自動で行ってくれる。しかし、インストールされているChromeのバージョンに合わないことがあるため、手動でダウンロードする。

## プロジェクトのファイルを編集

以下の3ファイルを編集する。

```gherkin:動作試験.feature
# language: ja
機能: 動作確認
  シナリオ: テストシナリオ
    前提 Googleのページを開く
    ならば ネコで検索する
```

```java:Stepdef.java
import com.codeborne.selenide.Selenide;

import cucumber.api.java.ja.ならば;
import cucumber.api.java.ja.前提;

public class Stepdefs {
    @前提("Googleのページを開く")
    public void googleのページを開く() {
        // Googleのページを開く
        Selenide.open("https://www.google.com/");
    }

    @ならば("ネコで検索する")
    public void ネコで検索する() {
        // 検索窓に"ネコ"と入力して検索
        Selenide.$("input[name=q]").setValue("ネコ").pressEnter();
    }
}
```

```java:RunCucumberTest.java
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/resources", plugin = {"pretty"}, monochrome = true)
public class RunCucumberTest {
    // テスト前に一度だけ行う処理
    @BeforeClass
    public static void setUp(){
        // ブラウザをChromeに設定
        Configuration.browser = WebDriverRunner.CHROME;

        // ブラウザのサイズを1024x768に設定
        Configuration.browserSize = "1024x768";

        // webdriverの場所を指定
        System.setProperty("webdriver.chrome.driver", "driver/chromedriver.exe");
    }
}
```

## Selenideテストの実行

先ほどと同様に`mvn test`で実行。ChromeでGoogleのページが開いて、"ネコ"が検索されれば成功。

# Allureによる結果出力

Allureによる結果出力を行う。先ほどのSelenideのテストの結果を成型する。

## Allure対応

`RunCucumberTest.java`に以下の修正を加える。

- `@CucumberOptions`の`plugin`に`io.qameta.allure.cucumber4jvm.AllureCucumber4Jvm`を追加。
- `SelenideLogger.addListener("AllureSelenide", new AllureSelenide().screenshots(true).savePageSource(false));`を`setUp()`メソッドの末尾に追加。

```java:RunCucumberTest.java
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;
import com.codeborne.selenide.logevents.SelenideLogger;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import io.qameta.allure.selenide.AllureSelenide;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/resources", plugin = {"pretty", "io.qameta.allure.cucumber4jvm.AllureCucumber4Jvm"}, monochrome = true)
public class RunCucumberTest {
    // テスト前に一度だけ行う処理
    @BeforeClass
    public static void setUp(){
        // ブラウザをChromeに設定
        Configuration.browser = WebDriverRunner.CHROME;

        // ブラウザのサイズを1024x768に設定
        Configuration.browserSize = "1024x768";

        // webdriverの格納先を指定
        System.setProperty("webdriver.chrome.driver", "driver/chromedriver.exe");

        // テスト失敗時にスクリーンショットをレポートに添付する設定
        SelenideLogger.addListener("AllureSelenide", new AllureSelenide().screenshots(true).savePageSource(false));
    }
}
```

わざとテストを失敗させるため、`Stepdef.java`の`ネコで検索する()`を書き換える。誤ったCSSセレクタを指定させる。

```java:Stepdef.java
    @ならば("ネコで検索する")
    public void ネコで検索する() {
        // 検索窓に"ネコ"と入力して検索
        // 誤ったセレクタを指定することで、テストを失敗させる
        Selenide.$("#Bad-Selector").setValue("ネコ").pressEnter();
    }
```

実行後、`autotest`フォルダに`allure-results`があることを確認する。

## Allureレポートの閲覧

コマンドプロンプトで`autotest`フォルダに移動して、以下のコマンドを実行。

```cmd:cmd
allure serve -h localhost -p 8080`
```

うまくいけばブラウザが立ち上がり、成形された結果を閲覧できる。Selenideのテスト失敗時にはスクリーンショットの確認も可能となっている。

```cmd
Generating report to temp directory...
Report successfully generated to C:\Users\<秘密>\AppData\Local\Temp\771554680061245798\allure-report
Starting web server...
2019-03-17 21:14:53.865:INFO::main: Logging initialized @8327ms to org.eclipse.jetty.util.log.StdErrLog
Server started at <http://localhost:8080/>. Press <Ctrl+C> to exit
```

![10.png](https://qiita-image-store.s3.amazonaws.com/0/279459/26811798-b8e4-70d4-3035-bd2948d63e90.png)

以上で基本的なことは終了です。

# 最後に

本稿ではCucumberでテストシナリオを作成し、SelenideでWebブラウザの操作を行い、Allureで結果の可視化を行う手順を示した。各ライブラリについて詳細を知りたければ、それぞれの公式サイトが参考になる。

そのうち、以下についての記事も製作しようと思う。

- Jenkinsを使ったAllureレポートの管理
- Allureレポートへのファイルの添付
- 各ステップ間のオブジェクト受け渡し