はじめに
React Testing Libraryを使ってReactのテストをしていた際、getByText
の文字列の指定方法でハマってしまいました。
同じ事例を繰り返さないための備忘録として事象と原因を書いていきます。
テストのコード
テストの対象のコード
function App() {
const [loading, setLoading] = useState(true);
/* 以下は今回実施したテストとは直接関係しないので省略 */
return (
<>
{loading && <p>now loading...</p>}
{/* 以下は今回実施したテストとは直接関係しないので省略 */}
</>
)
テストを実施したコード
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import App from "../App";
describe("テスト1", () => {
test("ローディング画面が存在している", () => {
render(<App />);
expect(screen.getByText("loading")).toBeInTheDocument();
});
});
テスト対象のコードには<p>now loading...</p>
という記述があったので、loading
という文字列も含まれていると思って上記のコードでテストを実施していた。
↓
テスト結果はFailedになった。
以下のようなエラーメッセージも出ていた。
Unable to find an element with the text: now loading. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
原因と対策
getByText
で文字列を引数とする場合は完全一致でないとTrueにならない。
そのためgetByText
で特定の文字列を指定したい場合は以下の2つの方法が考えられる。
①テストしたい文字列を完全一致するように指定する
expect(screen.getByText("now loading...")).toBeInTheDocument();
②正規表現を使って部分一致の条件を作る
expect(screen.getByText(/loading/)).toBeInTheDocument();
最後に
下記の参考資料に
文字列の引数が完全一致であるのに対し、正規表現は部分一致となる
と書かれているため、資料を読み込んでいれば防げるミスでした。
皆さんはgetByText
を使うときは完全一致の文字列を指定することを心がけてくd
参考資料