自動テストチュートリアル

Playwright、Seleniumなどの自動テストツールを学ぼう

要素の定義方法

要素の定義方法

Page Objectで要素を定義するいくつかの方法を紹介します。

方法1: readonlyプロパティ

最も基本的な方法です。

export class LoginPage {
  readonly usernameInput: Locator;
  readonly passwordInput: Locator;

  constructor(page: Page) {
    this.usernameInput = page.locator('#username');
    this.passwordInput = page.locator('#password');
  }
}

メリット: TypeScriptの型チェックが効く デメリット: 要素が多いとコードが長くなる

方法2: getterを使う

getterを使うと、プロパティ宣言が不要になります。

export class LoginPage {
  constructor(private page: Page) {}

  get usernameInput() {
    return this.page.locator('#username');
  }

  get passwordInput() {
    return this.page.locator('#password');
  }
}

メリット: コードがスッキリする デメリット: アクセスのたびにlocatorが生成される

方法3: アロー関数を使う

関数として要素を取得する方法です。

export const loginPage = {
  usernameInput: () => page().locator('#username'),
  passwordInput: () => page().locator('#password'),

  async login(username: string, password: string) {
    await this.usernameInput().fill(username);
    await this.passwordInput().fill(password);
  }
};

メリット: オブジェクトリテラルで書ける デメリット: pageの取得方法を工夫する必要がある

おすすめのパターン

小規模プロジェクト

readonlyプロパティがシンプルでおすすめ:

export class LoginPage {
  readonly usernameInput: Locator;

  constructor(page: Page) {
    this.usernameInput = page.locator('#username');
  }
}

中〜大規模プロジェクト

getterを使うとコードが整理しやすい:

export class LoginPage {
  constructor(private page: Page) {}

  // 要素
  get usernameInput() { return this.page.locator('#username'); }
  get passwordInput() { return this.page.locator('#password'); }
  get loginButton() { return this.page.getByRole('button', { name: 'Login' }); }

  // アクション
  async login(username: string, password: string) {
    await this.usernameInput.fill(username);
    await this.passwordInput.fill(password);
    await this.loginButton.click();
  }
}
🎯 ベストプラクティス
  • ロケーターはgetByRolegetByTestIdを優先
  • IDやclassは変更されやすいので避ける
  • 要素名は分かりやすい名前をつける