Seleniumで通信内容を全部Captureする


はじめに

Seleniumで検証する際に、対象URLのレスポンスだけでなくそこからajaxで取得しているjson(DOMにはロードされず、遷移のパラメータにのみ使用)の内容も検証する必要があったので、色々調べて試してみました。
まとめてくれているURLも結構ありますが、断片的だったり英語だったりするので、少しは役に立つかな?と思い記録することにしました。
なお、既存テストケースを流せる既存検証ツールの拡張なので

  • java限定
  • Chromeのみ可 or FireFoxのみ可はNG、少なくともどちらでも、できればそれ以外でも可

である必要がありました。

結論

BrowserMob ProxyのEmbedded Modeでのぞき見?することにしました。というかそれ以外のやり方が分かりませんでした。のぞき見した内容はHAR形式で取得できるので、そこから抽出して検証、の流れが問題なく実行できました。

課題

セキュリティ例外?やらが出ます。一応検証自体はできているのでろくに見ておらずほったらかしですが、検証ツールのログチェックにひっかかるので消さないと。。。

考えたこと、少し試した結果

  • HTTPステータスを取得するのと同様、WebDriver.manage().logs().get( LogType.xxx )的なやり方はないものか
  • WebDriverの通信コールバックかなんかないか?
  • (JavascriptExecutor)WebDriver.executeScript( "return xxx" )みたいにして取得できないものか
  • BrowserMob Proxyでキャプチャ

で、一番目は無理っぽい、二番目もわからず、三番目はどうやって変数にアクセスするか全く分からず、最後の方法でやることにしました。一、二、三番番目、その他の方法でもこうやればできるよ、っていうのがあれば教えていただけるとありがたいです。

やったこと

依存関係

pomに以下を追記しました。

pom.xml
<dependency>
    <groupId>net.lightbody.bmp</groupId>
    <artifactId>browsermob-core</artifactId>
    <version>2.1.5</version>
</dependency>

ソースはこんな感じ

初期化

import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.proxy.CaptureType;

DesiredCapabilities capabilities = null;
if ( /* Chromeの場合 */ ) capabilities = DesiredCapabilities.chrome();
else if ( /* FireFoxの場合 */ ) capabilities = DesiredCapabilities.firefox();
// else if などなど。。。

BrowserMobProxyServer bmpServer = null
EnumSet<CaptureType> captureTypeSet = EnumSet.noneOf( CaptureType.class );
if ( /* リクエストヘッダをキャプチャしたい */ ) captureTypeSet.add( CaptureType.REQUEST_HEADERS  );
if ( /* リクエストコンテンツをキャプチャしたい */ ) captureTypeSet.add( CaptureType.REQUEST_CONTENT  );
if ( /* レスポンスヘッダをキャプチャしたい */ ) captureTypeSet.add( CaptureType.RESPONSE_HEADERS );
if ( /* レスポンスコンテンツをキャプチャしたい */ ) captureTypeSet.add( CaptureType.RESPONSE_CONTENT );

if ( ! captureTypeSet.isEmpty() ) {
    bmpServer = new BrowserMobProxyServer();
    bmpServer.setTrustAllServers( true );
    bmpServer.enableHarCaptureTypes( captureTypeSet );

    if ( /* 外部プロキシを使いたい */ ) {
        try {
            bmpServer.setChainedProxy( new InetSocketAddress( /* 外部プロキシホスト */, /* ポート */ ) ) );
        }
        catch ( Exception e ) {
            // 例外処理
        }
    }
    bmpServer.start();
    capabilities.setCapability( CapabilityType.PROXY, ClientUtil.createSeleniumProxy( bmpServer ) );
}

ChromeOptions.merge( capabilities );
// とか
FirefoxOptions.merge( capabilities );
// とかやってWebDriverインスタンス生成

HARデータ取得

if ( null != browserMobProxyServer ) bmpServer.newHar( /* ラベル文字列 */ );

// SeleniumでアクセスしたりWaitしたり。。。

// HARデータ文字列
String har = null;
if ( null != bmpServer ) {
    StringWriter writer = new StringWriter();
    try {
        bmpServer.getHar().writeTo( writer );
        har = writer.toString();
    }
    catch ( Exception ex ) {
        // 例外処理
    }
}

終了処理

if ( null != bmpServer ) {
    bmpServer.stop();
}