バージョンを上げました。 https://t.co/jBGOLeZ6iR
— しまぶ (@shimabox) November 15, 2018
というわけでバージョンを上げました(v0.6.0)。
バージョンアップの内容
バージョンアップの内容は大まかに挙げるとこんな感じです。
- shimabox/selenium-downloader の組み込み
SMB\Screru\Screenshot\Screenshot- take(), takeFull(), takeElement()
- 引数のファイル名に拡張子が含まれていようと含まれていまいと拡張子は
.pngになるように統一 hoge.jpgで指定されていてもhoge.pngで出力- シグネチャの修正
- UnitTest用のページを外部(Google)から、内部(localhost)に変更
- テストではビルトインサーバーを利用します
上記のアップデートで自分の中では大体形が見えてきたので、再度使い方についてまとめてみたいと思います。
そもそもこれは何なのか
facebook/php-webdriver のちょっとしたラッパーライブラリです。
主に以下の機能を持ちます。
- PHPUnit用に組み込める関数群をTraitとして用意しています
- 画面のフルスクリーンキャプチャが撮れます
- 指定要素のキャプチャが撮れます
- 各ブラウザのwebdriverがあれば容易にテスト可能です
対応ブラウザは、
- Firefox
- Chrome
- Internet Explorer (windows)
のみとなっています(いまのところ)。
https://github.com/shimabox/screru
名前は screru(スクレル) です。
インストール
Composer で入れるか、git clone します。
Composer
$ composer require shimabox/screru $ cd vendor/shimabox/screru $ cp .env.default .env
clone
$ git clone https://github.com/shimabox/screru.git $ cd screru $ composer install
自分のところで composer instal | update した場合、.env.default ファイルをコピーして .env ファイルを作成します。
設定ファイルの修正 (.env | .env.default)
各設定を .env | .env.default ファイルで管理しています。
デフォルト設定を変更する必要がある場合は、
.env.defaultファイルをコピーして.envファイルを作成- その
.envファイルを修正
します。
.env ファイルが存在しなければ、.env.default ファイルを参照します。
$ vim .env // selenium server url SELENIUM_SERVER_URL='http://localhost:4444/wd/hub' // you can override the default User-agent OVERRIDE_DEFAULT_USER_AGENT='' // local port LOCAL_PORT=8000 // true to enable ENABLED_CHROME_DRIVER=true ENABLED_FIREFOX_DRIVER=true ENABLED_IE_DRIVER= // true to start headless chrome ENABLED_CHROME_HEADLESS=true // true to start headless firefox ENABLED_FIREFOX_HEADLESS=true // true to platform is windows IS_PLATFORM_WINDOWS= // describe the webdriver path if necessary CHROME_DRIVER_PATH='' FIREFOX_DRIVER_PATH='' IE_DRIVER_PATH=''
| Key | Description | Default | Example |
|---|---|---|---|
| SELENIUM_SERVER_URL | セレニウムサーバーのURLを定義しています. | http://localhost:4444/wd/hub | |
| OVERRIDE_DEFAULT_USER_AGENT | (SPのテストなど) デフォルトで使われるUser-agentを変更できます. | Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1 | |
| LOCAL_PORT | ユニットテストで使われるlocalhostのポート番号を定義しています. | 8000 | |
| ENABLED_CHROME_DRIVER | trueにするとChromeDriverが有効になります. | true | |
| ENABLED_FIREFOX_DRIVER | trueにするとgeckodriverが有効になります. | true | |
| ENABLED_IE_DRIVER | trueにするとIEDriverServerが有効になります. | blank(false) | |
| ENABLED_CHROME_HEADLESS | trueにするとChromeをヘッドレスモードで起動させます. | true | |
| ENABLED_FIREFOX_HEADLESS | trueにするとFirefoxをヘッドレスモードで起動させます. | true | |
| IS_PLATFORM_WINDOWS | Windowsでテストされているかどうか. Windowsでテストする場合必ずtrueにしてください. |
blank(false) | |
| CHROME_DRIVER_PATH | 必要に応じてChromeDriverのファイルパスを記述します(ローカルのものとか). 記載が無ければPATHを見にいきます. Windowsの場合、.exeファイルのファイルパスを書いたほうがよいです. |
blank | /home/user/screru/chromedriver |
| FIREFOX_DRIVER_PATH | 必要に応じてgeckodriverのファイルパスを記述します(ローカルのものとか). 記載が無ければPATHを見にいきます. Windowsの場合、.exeファイルのファイルパスを書いたほうがよいです. |
blank | /Applications/MAMP/htdocs/screru/geckodriver |
| IE_DRIVER_PATH | 必要に応じてIEDriverServerのファイルパスを記述します(ローカルのものとか). 記載が無ければPATHを見にいきます. Windowsの場合、.exeファイルのファイルパスを書いたほうがよいです. |
blank | /c/xampp/htdocs/screru/IEDriverServer.exe |
どうしてもこのへん面倒くさいのですが、、何か他にいい案があったら教えてください。
準備
selenium-server-standalone, ChromeDriver, geckodriver, IEDriverServer などなど必要なものをダウンロードします(zip や tar は適宜解凍してください)。
※ 以下は、現時点(2018/11/16) でのおすすめバージョンです
| Platform | selenium-server-standalone | ChromeDriver | geckodriver | IEDriverServer |
|---|---|---|---|---|
| Mac | 3.8.1 | 79.0.3945.36 | 0.26.0 | – |
| Windows(64bit) | 3.8.1 | 2.43 | 0.23.0 | 3.14.0 |
| Linux(CentOS 6.9) | 3.8.1 | – | 0.23.0 | – |
| Linux(Ubuntu trusty) | 3.8.1 | 2.43 | 0.23.0 | – |
ダウンロードが面倒くさい場合
必要な諸々をダウンロードするスクリプトがあるのでそれを使います。
- Mac の場合
$ php selenium_downloader.php -p m -d . -s 3.8.1 -c 79.0.3945.36 -g 0.26.0
- Windows の場合
$ php selenium_downloader.php -p w -d . -s 3.8.1 -c 2.43 -g 0.23.0 -i 3.14.0
- Linux の場合
$ php selenium_downloader.php -p l -d . -s 3.8.1 -g 0.23.0
shimabox/selenium-downloader を組み込んでいますので、こちらも参考にしてみてください。
macOS
前提条件として、javaが入っていなければインストールが必要です。
パスを通す
ChromeDriverとgeckodriverのパスを通します- e.g) ChromeDriver
$ mv chromedriver /usr/local/bin/ $ chmod +x /usr/local/bin/chromedriver
- e.g) geckodriver
$ mv geckodriver /usr/local/bin/ $ chmod +x /usr/local/bin/geckodriver
- e.g) ChromeDriver
任意のパスにあるドライバーを使う場合
任意のパスにあるドライバーを使いたい場合、.env ファイルの以下キーにドライバーのファイルパスを記述します。
※ 実行権限をつけてください(chmod +x)
e.g)
CHROME_DRIVER_PATH=/Applications/MAMP/htdocs/screru/chromedriver FIREFOX_DRIVER_PATH=/Applications/MAMP/htdocs/screru/geckodriver
selenium-server-standaloneの実行
seleniumを以下コマンドで立ち上げます。
$ java -jar selenium-server-standalone-3.8.1.jar -enablePassThrough false
windows(64bit)
前提条件として、javaが入っていなければインストールが必要です。
.env
- Edit
.envENABLED_FIREFOX_DRIVER=true ENABLED_CHROME_DRIVER=true ENABLED_IE_DRIVER=true // true to platform is windows IS_PLATFORM_WINDOWS=true // describe the webdriver path if necessary FIREFOX_DRIVER_PATH='geckodriver.exe のファイルパスを記述します' CHROME_DRIVER_PATH='chromedriver.exe のファイルパスを記述します' IE_DRIVER_PATH='IEDriverServer.exe のファイルパスを記述します'
※ 各ドライバーには実行権限をつけてください(
chmod +x)
IS_PLATFORM_WINDOWS の値は必ず true にしてください。
selenium-server-standaloneの実行
seleniumを以下コマンドで立ち上げます。
$ java -jar selenium-server-standalone-3.8.1.jar -enablePassThrough false
注意
Facebook\WebDriver\Exception\SessionNotCreatedException: Unexpected error launching Internet Explorer. Protected Mode settings are not the same for all zones. Enable Protected Mode must be set to the same value (enabled or disabled) for all zones.
テストを実行して上記エラーが表示されたら以下リンクを参照してみてください。
- Rantings of a Selenium Contributor: You’re Doing It Wrong: IE Protected Mode and WebDriver
- internet settings.png (2718×1068)
要は、IEのインターネットオプション-セキュリティにおいて、すべてのゾーンの設定を同じにすればいい(保護モードを有効にする)だけです。地味にめんどくさいけど。
Linux (CentOS 6.9)
java と Firefox と Xvfb のインストールが必要です(入っていなければ)。
java
- install
$ sudo yum -y install java
- version 1.8>=
$ java -version openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-b11) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)
Firefox
- install
$ sudo yum -y install firefox
or
$ sudo yum -y update firefox
- version 60.3.0
$ firefox -v Mozilla Firefox 60.3.0
Xvfb
- install
$ sudo yum -y install xorg-x11-server-Xvfb $ sudo yum -y groupinstall "Japanese Support"
パスを通す
geckodriverのパスを通します$ mv geckodriver /usr/local/bin/ $ chmod +x /usr/local/bin/geckodriver
任意のパスにあるドライバーを使う場合
任意のパスにあるドライバーを使いたい場合、.env ファイルの以下キーにドライバーのファイルパスを記述します。
※ 実行権限をつけてください(chmod +x)
e.g)
FIREFOX_DRIVER_PATH=/home/user/screru/geckodriver
.env
- Edit
.envENABLED_FIREFOX_DRIVER=true ENABLED_CHROME_DRIVER= ENABLED_IE_DRIVER=
selenium-server-standaloneの実行
シェルを用意しているのでそれを叩いたほうが楽かもしれません。
(Xvfb と selenium-server-standalone を起動させないといけないので)
- Run Xvfb & selenium-server-standalone
$ sudo sh start_selenium.sh
- Stop Xvfb & selenium-server-standalone & geckodriver
$ sudo sh kill_selenium.sh
Linux (Ubuntu trusty)
Ubuntu は申し訳ないですが以下の設定を参考にしてみてください。
(いずれ自前でも動かしてみます)
試してみる
上記手順を踏めば、seleniumは立ち上がっていると思いますので
- フルスクリーンのキャプチャ
- 要素のキャプチャ
の撮り方を簡単に書いてみます。
フルスクリーンのキャプチャ
SMB\Screru\Screenshot\Screenshot を使います。
<?php require_once '/vendor/autoload.php'; use SMB\Screru\Screenshot\Screenshot; // Screenshotをnewします $screenshot = new Screenshot(); // ファイル名 $fileName = 'full.png'; // キャプチャファイルを保存するディレクトリパス $captureDirectoryPath = '/xxx/capture_dir/'; // これでフルスクリーンのキャプチャが撮れます // $driverは Facebook\WebDriver\Remote\RemoteWebDriver です $screenshot->takeFull($driver, $captureDirectoryPath, $fileName);
要素のキャプチャ
SMB\Screru\Elements\Spec, SMB\Screru\Elements\SpecPool, SMB\Screru\Screenshot\Screenshot を使います。
<?php
require_once '/vendor/autoload.php';
use SMB\Screru\Elements\Spec;
use SMB\Screru\Elements\SpecPool;
use SMB\Screru\Screenshot\Screenshot;
// Screenshotをnewします
$screenshot = new Screenshot();
// ファイル名
$fileName = 'full.png';
// キャプチャファイルを保存するディレクトリパス
$captureDirectoryPath = '/xxx/capture_dir/';
// 要素のセレクターを定義します
$spec = new Spec('#id', Spec::GREATER_THAN_OR_EQUAL, 1);
$spec2 = new Spec('.class', Spec::GREATER_THAN, 1);
// SpecPoolに突っ込みます
$specPool = (new SpecPool())
->addSpec($spec)
->addSpec($spec2);
// これで要素のキャプチャが撮れます
// $driverは Facebook\WebDriver\Remote\RemoteWebDriver です
$screenshot->takeElement($driver, $captureDirectoryPath, $fileName, $specPool);
なお、Screenshot::take() は、Facebook\WebDriver\Remote\RemoteWebDriver::takeScreenshot() のラッパーです。
上記を踏まえたデモ (Chrome)
<?php
require_once '/vendor/autoload.php';
use SMB\Screru\Elements\Spec;
use SMB\Screru\Elements\SpecPool;
use SMB\Screru\Factory\DesiredCapabilities;
use SMB\Screru\Screenshot\Screenshot;
use SMB\UrlStatus;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\WebDriverBrowserType;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverBy;
if (getenv('ENABLED_CHROME_DRIVER') !== 'true') {
die('Please enable ChromeDriver.');
}
$host = getenv('SELENIUM_SERVER_URL');
// Use chromedriver.
$cap = new DesiredCapabilities(WebDriverBrowserType::CHROME);
$driver = RemoteWebDriver::create($host, $cap->get());
// Window size.
$w = 600;
$h = 800;
$dimension = new WebDriverDimension($w, $h);
$driver->manage()->window()->setSize($dimension);
$url = 'https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr';
// 指定URLへ遷移 (Google)
$driver->get($url);
// 検索Box
$findElement = $driver->findElement(WebDriverBy::name('q'));
// 検索Boxにキーワードを入力して
$findElement->sendKeys('Hello');
// 検索実行
$findElement->submit();
// コンテンツの中身が可視化されるまで10秒待つ(#botstuffをターゲットに)
// もしも要素が現れないで10秒経った場合,
// 'Facebook\WebDriver\Exception\TimeOutException' がThrowされます
$driver->wait(10)->until(
WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::id('botstuff'))
);
// タイトルが `Hello - Google search` になっているかの確認
if ($driver->getTitle() !== 'Hello - Google Search') {
throw new Exception('fail $driver->getTitle()');
}
// HttpStatus of url
$status = UrlStatus::get($driver->getCurrentURL());
if ($status->is200() === false) {
throw new Exception('fail HttpStatus');
}
/*
|------------------------------------------------------------------------------
| Capture test.
|------------------------------------------------------------------------------
*/
$fileName = 'capture_demo';
$ds = DIRECTORY_SEPARATOR;
$captureDirectoryPath = realpath(__DIR__ . $ds . 'capture') . $ds;
// Create a Screenshot.
$screenshot = new Screenshot();
// 全画面キャプチャ (拡張子は .png になります)
$screenshot->takeFull($driver, $captureDirectoryPath, $fileName . '_full.png');
// 要素のセレクターを定義して
$spec = new Spec('.RNNXgb', Spec::GREATER_THAN_OR_EQUAL, 1);
$spec2 = new Spec('.brs_col', Spec::GREATER_THAN, 1);
// SpecPoolに突っ込む
$specPool = (new SpecPool())
->addSpec($spec)
->addSpec($spec2);
// 要素のキャプチャ (拡張子は .png になります)
$screenshot->takeElement($driver, $captureDirectoryPath, $fileName, $specPool);
// Close window.
$driver->close();
動かしてみたときの gif はここで見れます。
キャプチャ
上記デモでとったキャプチャはこちら。
- capture_demo_full.png
- capture_demo_0_0.png (.RNNXgb)
- capture_demo_1_0.png (.brs_col)
- capture_demo_1_1.png (.brs_col)
IE (Windows)
上記の
$cap = new DesiredCapabilities(WebDriverBrowserType::CHROME);
を
$cap = new DesiredCapabilities(WebDriverBrowserType::IE);
こうするだけで、IEでもフルスクリーンキャプチャとれるぞ(もちろん要素も)。
※ IEDriverServer.exe の用意と .env の修正が必要
PHPUnitに組み込む
PHPUnit用の Trait\SMB\Screru\Traits\Testable を用意しているので以下のように組み込みます。
// \PHPUnit_Framework_TestCase を継承したクラスでuseします
class Sample extends \PHPUnit_Framework_TestCase
{
// use Trait
use \SMB\Screru\Traits\Testable {
setUp as protected traitSetUp;
tearDown as protected traitTearDown;
}
/**
* setUp
*/
protected function setUp()
{
$this->traitSetUp();
}
/**
* tearDown
*/
protected function tearDown()
{
$this->traitTearDown();
}
// do someting ...
}
フルスクリーン、要素のキャプチャを撮る
- フルスクリーンキャプチャ
Testable::takeFullScreenshot();
- 要素キャプチャ
Testable::takeElementScreenshot();
を使います。
※ Testable::takeScreenshot(); は、Facebook\WebDriver\Remote\RemoteWebDriver::takeScreenshot() のラッパーです
テスト(assertion)失敗時にキャプチャを撮る
上記のTrait \SMB\Screru\Traits\Testable を use したのち、プロパティtakeCaptureWhenAssertionFails の値を true にします。
class Sample extends \PHPUnit_Framework_TestCase
{
// use Trait
use \SMB\Screru\Traits\Testable {
setUp as protected traitSetUp;
tearDown as protected traitTearDown;
}
// Set this property to true
protected $takeCaptureWhenAssertionFails = true;
/**
* setUp
*/
protected function setUp()
{
$this->traitSetUp();
}
/**
* tearDown
*/
protected function tearDown()
{
$this->traitTearDown();
}
// do someting ...
}
それか、以下関数を必要な箇所で呼びます。
(こっちのほうがいいですね)
// テスト失敗時のキャプチャ処理を有効化します $this->enableCaptureWhenAssertionFails(); // テスト失敗時のキャプチャ処理を無効化します $this->disableCaptureWhenAssertionFails();
その他設定
- デフォルトのseleniumサーバーのURLを変更する場合
$ vim .env // selenium server url SELENIUM_SERVER_URL='your selenium server url'
-
デフォルトのUserAgentを変更する場合(SPのテストで使われる)
$ vim .env // you can override the default User-agent (Android 7.1.1) OVERRIDE_DEFAULT_USER_AGENT='Mozilla/5.0 (Linux; Android 7.1.1; Nexus 5X Build/N4F26I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36'
Headless Chrome
最新のChromeであれば以下設定でヘッドレスモードになります。
※ trueにしなければ普通にブラウザが立ち上がります
- Edit
.env// true to start headless chrome ENABLED_CHROME_HEADLESS=true
Headless Firefox
最新のFirefoxであれば以下設定でヘッドレスモードになります。
※ trueにしなければ普通にブラウザが立ち上がります
- Edit
.env// true to start headless firefox ENABLED_FIREFOX_HEADLESS=true
テスト
ビルトインサーバを立ち上げます(立ち上げないとテストこけます)
$ php -S 127.0.0.1:8000 -t tests/web
ポート番号は .env ファイルの LOCAL_PORT の値と揃えます。
テスト実行
$ vendor/bin/phpunit
おわりに
準備がめんどくさい印象が強いですが、それさえ出来てしまえば簡単なe2eテストはサクッと書けるかと思います。
(エビデンスが求められるところが未だにあるかわからないですが)キャプチャもとれるし。
※ ただし、スクロールバーの操作を伴うものやjsなどで小難しいことをしているページだと今のところ対応はしてません。そこは独自にがんばってもらう方向で。。
あとは、よくありそうなパターン (目視が必要なやつとか、metaタグとかの確認とか) を簡単に確認出来るような機能を追加していきたいなぁと思っています。
ではでは。



