LoginSignup
71
71

More than 5 years have passed since last update.

PHPUnit + php-webdriver でWebUIのテストを書く

Last updated at Posted at 2015-11-23

WebUIのテストはwebdriverjs + jasmine-nodeで書いていましたが、PHPでも書いてみます。

WebAPIのテストはこちら

前提

  • composerがインストールされている
  • Mac(El capitan)

ホームディレクトリ内にtestというフォルダを作ってその中で作業するものとします。

準備

ライブラリのダウンロード

#ディレクトリ作成
cd ~/
mkdir test
cd test

#phpunitとwebdriverのインストール
composer require phpunit/phpunit
composer require facebook/webdriver

Selenium standaloneサーバのダウンロードと起動

ここから最新のものをダウンロードします。

wget http://selenium-release.storage.googleapis.com/2.48/selenium-server-standalone-2.48.2.jar

ダウンロードしたら、起動しておきます。

java -jar selenium-server-standalone-2.48.2.jar

標準では4444ポートで起動するようです。2.48.2の部分は、ダウンロードしたファイルに合わせて変更して下さい。

chromedriverのダウンロード

ここから、最新のchromedriverをダウンロードして、PATHの通ったディレクトリにコピーします。

wget http://chromedriver.storage.googleapis.com/2.20/chromedriver_mac32.zip
unzip chromedriver_mac32.zip
mv chromedriver /usr/local/bin/

テストを書く(テスト対象)

制御用のサイトを準備する

localhost/test/index.php(html)を用意して、下記のようなHTMLを書きました。
とりあえずForm要素の制御をしたいので、主要要素を書きます。デザインは無視です。

ポイントとしては

  • 主要なForm要素の制御を調べる
  • Confirm等のアラートの制御を調べる

という感じ。

<!doctype html>
<html>
<head>
<title>top</title>
</head>
<body>
<h3>input</h3>
<form action="res.php" method="post">
<!-- text -->
name:<input type="text" name="name" id="name"><br>
email:<input type="text" name="email" id="email"></br>

<!-- radio -->
gender:
 男:<input type="radio" name="gender" value="男" id="gender1">
 女:<input type="radio" name="gender" value="女" id="gender2"><br>
<!-- checkbox -->
media:
 Web:<input type="checkbox" name="web" value="Web" id="media1">
 TV:<input type="checkbox" name="TV" value="TV" id="media2"><br>

<!-- select -->
<select name="area" id="area">
    <option value="選択して下さい">選択して下さい</option>
    <option value="関東">関東</option>
    <option value="関西">関西</option>
</select><br>

<!-- textarea -->
ご意見:
<textarea id="note"></textarea><br>

<!-- hidden 対応できない -->
<input type="hidden" name="key" value="" id="key">

<!-- submit -->
<input type="submit" value="push" id="btn">

</form>
<!--script-->
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script>
$(function(){
    $("#btn").click(function(){
        if(confirm('いいですか?')){
            //何もしない(action先へ)
        }else{
            return false;
        }
    });
});
</script>
</body>
</html>

res.phpというやつに飛ばしていますので、そのコードも。

<?php

    //受け取ったPOSTを表示
    print_r($_POST);

    //初期化(別にいらない)
    $name = "xxx";
    $email = "xxx@xxx.com";

    //受け取り
    if(isset($_POST['name'])) $name = $_POST['name'];
    if(isset($_POST['email'])) $email = $_POST['email'];
?>
<!doctype html>
<html>
<head>
<title>res</title>
</head>
<body>
name:<span id="name2"><?php echo $name; ?></span><br>
email:<span id="email2"><?php echo $email; ?></span>
</body>
</html>

値がきているのを調べるのがめんどくさいのでprint_r($_POST)で表示させています。
あと、受け取った値を調べたいのでnameとemailだけタグに入れてidを振ってみました。

テストを書く(テストコード)

testフォルダの中にさらにtestsフォルダを作り、その中にsampleTest.phpというファイルを作成し、テストを書いて行きます。

最小限のコード

まずは、環境がきちんと動いているかチェックしてみましょう。

cd ~/test
mkdir tests
vi tests/sampleTest.php

sampleTest.phpを編集します。

<?php

class sampleTest extends PHPUnit_Framework_TestCase
{
    public function testFunction()
    {
        //test assertion
        $this->assertEquals("hoge","hoge");
    }
}

実行

実行してみます。

cd ~/test
./vendor/bin/phpinit --colors tsets/

OK (1 test, 1 assertion)

グリーンでOK (1 test, 1 assertion)とでればOKです。

Chrome制御のテストを書いてみる

<?php

//必要クラスの読み込み(テストコードが少しでも短くなうるよう指定しておく)
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 sampleTest extends PHPUnit_Framework_TestCase
{
    public function testWebUI()
    {

        //準備 --------------------------------------------------------

        //(java -jar java -jar selenium-server-standalone-2.48.2.jar済である必要あり)
        $host = 'http://localhost:4444/wd/hub';
        //chromedriverを指定(chromedriverをダウンロードして/user/local/bin等に入れておく。
        $driver = RemoteWebDriver::create($host, DesiredCapabilities::chrome());

        // //テストするサイトに移動
        $driver->get('http://localhost/test/index.php');

        //最後の要素が読み込まれるまで待つ(sec,millisec)
        //とにかく待つならsleep(3)とかでも可?(未確認)
        $driver->wait(10,500)->until(
            //WebDriverExpectedCondition::titleIs('top')
            WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::cssSelector('#btn'))
        );

        //Form制御 -----------------------------------------------------

        //text:name選択
        $driver->findElement(WebDriverBy::cssSelector('#name'))->click();
        //入力
        $driver->getKeyboard()->sendKeys("hoge");

        //text:email選択
        $driver->findElement(WebDriverBy::cssSelector('#email'))->click();
        //入力
        $driver->getKeyboard()->sendKeys("hoge@hoge.com");

        //radio(clickだけでよい)
        $driver->findElement(WebDriverBy::cssSelector('#gender2'))->click();

        //checkbox(clickだけでよい)
        $driver->findElement(WebDriverBy::cssSelector('#media1'))->click();

        //select
        $driver->findElement(WebDriverBy::cssSelector('#area'))->click();
        //選択(sendKeyでよい)
        $driver->getKeyboard()->sendKeys("関西");

        //textarea
        $driver->findElement(WebDriverBy::cssSelector('#note'))->click();
        //入力
        $driver->getKeyboard()->sendKeys("何もありません。");

        //submit click
        $driver->findElement(WebDriverBy::cssSelector('#btn'))->click();

        //confirm ok
        $driver->switchTo()->alert()->accept();

        //confirm cancel
        // $driver->switchTo()->alert()->dismiss();

        //ページ移動 ======

        //移動先で要素取得
        $email = $driver->findElement(WebDriverBy::cssSelector('#email2'))->getText();

        //assert ------------------------------------------------------

        //評価
        $this->assertEquals("hoge@hoge.com",$email);
        $this->assertRegExp('/^h.+@.+com$/',$email);

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

こんな感じです。
少し複雑なのですが、一度パターンを書いてしまえば、それほど難しくはありません。

実行してみます。

./vendor/bin/phpinit --colors tsets/
Facebook\WebDriver\Exception\WebDriverCurlException: Curl error thrown for http POST to /session with params: {"desiredCapabilities":{"browserName":"chrome","platform":"ANY"}}

Failed to connect to localhost port 4444: Connection refused

このようなエラーが出た場合は、selenium serverが起動していません。起動させましょう。

java -jar selenium-server-standalone-2.48.2.jar

その他

覚えてると便利そうなwebdriverメソッド

githubのサンプルページWikiなどが参考になります。が、その他にもいろいろ。

  • WebDriverExpectedCondition::presenceOfAllElementsLocatedBy(WebDriverBy::cssSelector('#hoge'))
  • WebDriverExpectedCondition::titleIs('top')
  • \$driver->getPageSource()
  • \$driver->getTitle()
  • \$driver->findElement(WebDriverBy::linkText('click here'))->click()
  • \$driver->takeScreenshot('test.png')

最低限のassertメソッド

  • assertEquals(\$expect,\$var) $expectと$varが等しいか?
  • assertRegExp(\$ptn, \$var) 正規表現にマッチするかどうか?
  • assertNull(\$var)
  • assertTrue(\$var)
  • assertFalse(\$var)
  • assertCount(\$num,\$array)
  • assertEmpty(\$array)

Laravelを利用している場合は標準以外に拡張されたassertも使えます。
詳しくはここ

LaravelのQueryBuilderやEloquentを使う

UIやAPIのテストを実行した結果、DBに正常に値が書き込まれているかをチェックしたくなります。もちろん普通にPDOでコードを書いてもいいですが、Laravelに慣れてる場合、QueryBuilderやEloquentが使いたくなります。その場合は、こちらを参考にしてください。

71
71
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
71