1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Symfony ComponentAdvent Calendar 2022

Day 19

実際のブラウザを使ってリクエスト処理する、"Panther"

Last updated at Posted at 2022-12-18

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.xml.dist
<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を利用します。

QiitaTest.php

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の方がよいかなと思います。

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?