要素が動的なデータを含む場合、どうすればテストを安定させられますか?
  • 16 Jan 2023
  • 1 分で読めます
  • 投稿者
  • ダーク
    ライト

要素が動的なデータを含む場合、どうすればテストを安定させられますか?

  • ダーク
    ライト

記事の要約

ターゲット要素に、シナリオ記録時と異なるデータ/テキストがある場合の、「対象要素が見つかりませんでした」エラーのトラブルシューティングガイドです。

このページでは、動的なデータに対してテストの実行を安定させる方法を紹介します。

原因

テスト実行時、テスト実行エンジンは要素の内部のテキストを見て、その要素が記録されたものと同じかどうかを確認します。
要素の同一性は、その中のテキストやデータだけで決まるわけではありませんが、日付、名前、メールアドレスなどの動的なデータは、「対象要素が見つかりませんでした」エラーを引き起こす可能性があります。

解決方法

1. CSSセレクターを使用する

CSSのセレクターを使用するのが、最も手っ取り早い対処法です。
例を見てみましょう。
下のスクリーンショットでは、最新記事がページの上半分に表示されているのがわかります。新しい記事が作成されると、タイトル、日付、著者が変わり、古い記事はページの下半分にあるカードのようなリストに移動されます。

newest-title

最新記事のタイトルがクリックされたことを確認するために、このように指定します。

div.LatestPost h1

dynamic-data-css-selector-example

(CSSのセレクターの基本を学ぶには、CSSセレクターを使いこなすをご覧ください。)

2. ウェブサイトの構造を更新する

テスト実行エンジンは、HTMLの情報を使って要素を識別しています。
各要素をよりユニークにすることで、テストをより安定させることができます。
最も一般的な修正は、span, div などの汎用的な要素を、より意味のあるもの(専門用語で「セマンティック」)に置き換えることです。

❌ 手がかりの少ないHTML構造

<div>
    <div>
        <div class="bold big">This is the page title</div>
        <div>
            Date: <span class="gray small">Jan 1, 2021</span>
        </div>
        <div>John</div>
    </div>
</div>

✅ より多くの手がかりを持つHTML構造

<main>
    <article>
        <h1>This is the page title</h1>
        <p id="posted-at" aria-label="date" >
            Date: <time datetime="2021-01-01">Jan 1, 2021</time>
        </p>
        <p id="written-by" aria-label="author">John</p>
    </article>
</main>

最初の例のブログページに戻ると、新しい記事が出てきてもCSSセレクターを使わずに最新記事のタイトルを取得することができます。
最新記事のタイトルは h1 で、つまりページのトップレベルのヘッダーであるのに対し、古い記事のタイトルは h3 です。テスト実行エンジンはこの違いを利用して、どのタイトルが最新の記事のものかを区別することができます。

no-css-selector.png

ウェブサイトの構造を改良して、より意味のあるものにすることは、低コストでできることではないかもしれません。しかし、特に効果的なCSSセレクターが見つからない場合は、試してみる価値があります。

JSステップを使用する

以下のように、期待されるテキストを持つ要素にクエリを発行することができます。

const expectedText = "Dec 15, 2021";
const allSpanElementsInPage = document.querySelectorAll("span");

// You need to convert the NodeList returned by querySelector to an Array
// to use the filter method.
const filteredElements = Array.from(allSpanElementsInPage).filter(
    (el) => {
        return el.innerText === expectedText;
    }
);

if (filteredElements.length === 1) {
    // Perform action as needed. For example, clicking.
    filteredElements[0].click();
} else if (filteredElements.length === 0) {
   throw new Error("No elements found with JS")
} else {
   throw new Error(`Could not determine single element. ${filteredElements.length} found.`)
}

関連記事


この記事は役に立ちましたか?

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.