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が使いたくなります。その場合は、こちらを参考にしてください。