あくまで個人的なメモ

あくまで個人的なメモ

Puppeteer で Headless Chromeを操ってE2Eテストする(予定) - PageObjects編

E2Eテストを書くにあたりやはりPageObjectsパターンによる記述をするべきではないかと思い至った。JavaScript力低いので書き方的にアレな点があればこっそり教えてほしいです。

PageObjectパターンとは

PageObjects · SeleniumHQ/selenium Wiki · GitHub を読め(乱暴

ここではテスト対象のWebページ(を構成するパーツ)をPageObjectのクラスで定義することにする。 構成パーツに関しては Atomic Design で語られる分類法に基づくコンポーネント定義を基本に置くとわかりやすい気がする。

最小単位はAtoms。これより小さな単位でPageObjectを作らない。 基本単位はOrganismsになると思う。(複数のモジュールで構成されるページ構成要素)

PageObjectsを作る

前回Google検索のテストを改造する。 半日悩んだ程度なのでこれがベストだとは思ってない。より良いやり方/書き方があれば教えて欲しい(他力本願)

main.js

const puppeteer = require('puppeteer'),
  assert = require('assert')
  GooglePage = require('./pages/GooglePage');

describe('puppeteer test', function() {
  this.timeout(20000);

  // expose variables
  before (function (done) {
    puppeteer
      .launch({
        headless: true,
        timeout: 200000
      })
      .then(function (browser) {
        global.browser = browser;
        done();
      });
  });

  // close browser and reset global variables
  after (function () {
    browser.close();
  });

  // 検索する。場合によって検索結果の件数が違うので注意。
  it('search google.', async function() {
    var g = new GooglePage(browser);
    await g.open();
    await g.typeSearchWord("puppeteer");
    await g.submit();
    let links = await g.result();
    assert(links.length === 10);
    await g.close();
  })

  // 検索キーワード変えて実行。以下同じ。
  it('search google 2', async function() {
    var g = new GooglePage(browser);
    await g.open();
    await g.typeSearchWord("power-assert");
    await g.submit();
    let links = await g.result();
    assert(links.length === 10);
    await g.close();
  })
});

pages/GooglePage.js

const puppeteer = require('puppeteer');
// googleの表現
//  検索ワードの入力
//  検索
//  検索結果は別のページオブジェクトにするべきだが今回一つにまとめてしまう。

class GooglePage {
    constructor(browser, page) {
        this.browser = browser;
        this.page = page;
    }
    async open() {
        if (this.page == undefined) {
            this.page = await this.browser.newPage();
        }
        await this.page.goto('https://www.google.com/');
    }
    async typeSearchWord(word) {
        this.word = word;
        await this.page.type("#lst-ib", this.word);
    }

    async submit() {
        await this.page.click('input[name="btnK"]');
        await this.page.waitForSelector('h3 a');
    }

    async result() {
        return await this.page.$$('h3.r a');
    }

  async close() {
    await this.page.close();
  }
}

module.exports = GooglePage;