Laravel5.2でPHPUnit使ってE2Eテストをする手順

# 必要なもの
- **Mac**
- **Laravel5.2**  
  Laravelの別バージョンを使いたい場合はphpunit、phpunit-selenium、webdriverのバージョンを調整する必要があるかもしれない。
- **selenium-server-standalone**  
  chromedriverを使うための中継サーバー
- **chromedriver**  
  ChromeのAPIを呼び出すことでブラウザの操作を行うドライバ（Selenium WebDriver）
- **phpunit**  
  Laravelに最初から付いてくるphpのユニットテストツール
- **php-webdriver**  
  Selenium WebDriverをPHPで操作するためのライブラリ


# selenium-server-standaloneをhomebrewでインストール
```console
brew update
brew install selenium-server-standalone
selenium-server --version
```
selenium-server --versionを叩いて「javaコマンドラインツールを使用するには、JDKをインストールする必要があります」というエラーが出た場合はjavaのJDKをインストールしてください。


# chromedriverをhomebrewでインストール
```console
brew install chromedriver
```
# Laravelアプリのcomposer.jsonを書き換えてパッケージをインストールする
- phpunit/phpunit ~5.0
- facebook/webdriver 1.2.0

※phpunitはLaravel5.2プロジェクト作成時にインストールされるバージョンよりアップグレードすることになります。

※phpunit-seleniumも使いたい人は以下のバージョンでインストールしてください。
- phpunit/phpunit-selenium 3.0.*

composer.json

```json
    "require-dev": {
        "fzaninotto/faker": "~1.4",
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "~5.0",
        "facebook/webdriver": "1.2.0",
        "symfony/css-selector": "2.8.*|3.0.*",
        "symfony/dom-crawler": "2.8.*|3.0.*"
    },
```
composer.jsonを書き換えたら、composer updateを実行。

```console
composer update
```
# とりあえずテストしてみる

ExampleTest.phpを適宜テストが通るように書き換えてから、アプリルートで実行。

```console
./vendor/bin/phpunit tests/ExampleTest.php
```
緑色で「OK (1 test, 2 assertions)」と出れば無事にphpunitは使えてます。

# BrowserTest.phpを作成

ExampleTest.phpをコピーしてBrowserTest.phpを作ります。

BrowserTest.php

```php

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

use Facebook\WebDriver;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\Remote;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;

class BrowserTest extends TestCase
{
    /**
     * A basic functional test browser.
     *
     * @return void
     */
    public function testBrowser()
    {
        // あらかじめselenium-serverを起動しておく必要がある
        $host = 'http://localhost:4444/wd/hub';

        // chrome ドライバーの起動
        $driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());

        // テストページへ遷移
        $driver->get('http://example.com');

        // .last-buttonが読み込まれるまで最大10秒待つ、その間500msでリトライする
        $driver->wait(10,500)->until(
            WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::cssSelector('.last-button'))
        );

        // .modal-openボタンをクリック
        $driver->findElement(WebDriverBy::cssSelector('.modal-open'))->click();

        //ブラウザを閉じる
        $driver->close();
    }
}
```

# selenium-serverを起動

テストを走らせる前に、ターミナルで別窓を開いてselenium-serverを起動しておく。

```console
selenium-server
```

selenium-serverはデフォルトでポート4444で立ち上がるので、コード内でlocalhost:4444と指定している人はポートを指定する必要はない。

ポートに別の番号を割り当てた人は

```console
selenium-server -p 8080
```

このようにしてポートを指定して立ち上げる。

# E2Eテストを実行

```console
./vendor/bin/phpunit tests/BrowserTest.php
```

バックグラウンドでブラウザが立ち上がり、自動でごちゃごちゃやってウィンドウを閉じ終わる。
そして、緑で「OK (1 test, 0 assertions)」と表示されたらテストは成功。

クリックする要素が見つからないなどのエラーがある場合は、
「ERRORS!
Tests: 1, Assertions: 0, Errors: 1.」とオレンジ色でエラーが表示される。

# 編集後記
ひとまずインストールしてテストができるところまで確認したので、これから実際にいろいろテストコードを書いて使い心地などを検証していくつもりです。

Laravel Duskが使えないLaravelのバージョンでも、このように自力で頑張って入れれば簡単にE2Eテストができるということが分かりました。

皆さんもお試しあれ。