Symfony Component Advent Calendar 2022の19日目の記事です。
最初に
SymfonyはPHPのフレームワークのひとつです。しかし、公式サイトの説明文には
Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
(SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。)
と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。
今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。
※記事内ではautoloadのインポートは省略します。
実際のブラウザを使ってリクエスト処理する、"Panther"
Pantherは、E2Eテストやスクレイピングを実際のブラウザを使って行うコンポーネントです。
インストール
# E2Eテストで使う場合
composer require symfony/panther --dev
# スクレイピングで使う場合
composer require symfony/panther --dev
Webドライバーインストール
Panther
はWebドライバーを利用します。まずはローカルマシンにWebドライバーをインストールします。
# Mac
brew install chromedriver geckodriver
# Windows
choco install chromedriver selenium-gecko-driver
# Ubuntu
apt install chromium-chromedriver firefox-geckodriver
Webドライバーの検出
次は、プロジェクトで利用するWebドライバーを検出します。drekelmans/bdi
を使って検出します。
composer require dbrekelmans/bdi --dev
vendor/bin/bdi detect drivers
このコマンドを実行することで、プロジェクト内にdrivers
ディレクトリが作成され、そこにWebドライバーが保存されます。
スクレイピング
スクレイピングする際はHttpClientと似たような感覚で行えます。各要素へのアクセスはCSSセレクタ, XPathなどが利用できますが、CSSセレクタが扱いやすいのではないかなと思います。
use Symfony\Component\Panther\Client;
// Chromeの場合
$client = Client::createChromeClient();
// Firefoxの場合
$client = Client::createFirefoxCLient();
// Qiitaトップにアクセス
$client->request('GET', 'https://qiita.com/');
// アドベントカレンダーのリンククリック
$client->clickLink('Advent Calendar');
// 指定されたセレクタが出力されるまで待つ
$crawler = $client->waitFor('main > section.css-1avseb1 > div > div.css-er6if3 > ul > li:nth-child(4) > a > p > span:nth-child(2)');
// 選択したセレクターでテキストを取得して出力
$io->text($crawler->filter('main > section.css-1avseb1 > div > div.css-xi606m > h2')->text());
// 現在のページのスクリーンショットを撮る
$client->takeScreenshot(__DIR__ . '/screenshot.png');
E2Eテスト
E2Eテストで利用する場合、phpunit.xml
を追記します。
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/bootstrap.php"
convertDeprecationsToExceptions="false"
>
...
<!-- ここ追加 -->
<extensions>
<extension class="Symfony\Component\Panther\ServerExtension" />
</extensions>
</phpunit>
そして、専用のテストケースクラスPantherTestCase
を利用します。
use Symfony\Component\Panther\PantherTestCase;
class QiitaTest extends PantherTestCase
{
public function test(): void
{
$client = static::createPantherClient();
$client->request('GET', 'https://qiita.com/');
$this->assertPageTitleContains('Qiita');
$this->assertSelectorTextContains('#New2GlobalHeader-react-component-2d53bd05-4c4a-411f-bdbf-40fba84ebbce > div > div > a:nth-child(9)', 'Advent Calendar');
// リンククリックして移動
$client->clickLink('Advent Calendar');
$client->waitFor('main > section.css-1avseb1 > div > div.css-er6if3 > ul > li:nth-child(4) > a >
$this->assertSelectorTextContains(''main > section.css-1avseb1 > div > div.css-xi606m > h2', 'カテゴリー');
}
}
Client
の使い方はスクレイピング時と同様です。PantherTestCase
にブラウザでの挙動やテキスト内容確認のアサーションが追加されています。
まとめ
今回はPanther
の紹介でした。E2EテストにはCodeceptionなどもありますが、Panther
であれば、PantherTestCase
が利用でき、Symfonyとの相性もよいので、Symfony内で使うのであればPanther
の方がよいかなと思います。