問題
React + Jestでテストを書いたところ、以下のような警告やエラーに遭遇した。
// 警告
console.error
Each child in a list should have a unique "key" prop.
Check the render method of `select`. It was passed a child from PracticePage. See https://react.dev/link/warning-keys for more information.
// エラー
● テストケース名
Unable to find an element with the text: /期待される文言/i. 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.
Ignored nodes: comments, script, style
状況
- あるテストファイルにJestのテストが20個くらい入ってる
- 前は全部通ってたのに、急にエラーが出るようになった
- VSCodeのターミナルで実行するとエラーは出ず、全部通る
- iTermとかGitHub Actionsでテストを回すとエラー
- Jest Runnerで個別にテストを実行した場合は問題なく通る
- 実行する環境や方法によって結果がバラバラで、何が原因なのか分からない
解決方法
- 20個あるテストの中で、エラーになるテストを特定
- 問題のあるテストだけを別のテストファイルに分けて移動
→ エラーが出なくなった - mockデータが他のテストで書き換わってしまい、それがエラーの原因だった
- mockデータを毎回初期化するようにしたら、すべてのテストが安定して通るようになった
test.tsx
// 修正前のmock
const userWords = [
{ id: 1, word_name: "hello", user_id: mockDummyUser.id},
{ id: 2, word_name: "world", user_id: mockDummyUser.id },
];
// ...
test.tsx
// 修正後のmock
type Word = {
id: number;
word_name: string;
};
const initialUserWords = [
{ id: 1, word_name: "hello", user_id: mockDummyUser.id},
{ id: 2, word_name: "world", user_id: mockDummyUser.id },
];
let userWords: Word[] = [];
// ...
// 各テスト実行前に必ず実行される初期化処理
beforeEach(() => {
userWords = JSON.parse(JSON.stringify(initialUserWords));
// ...
原因
-
Each child in a list should have a unique "key" prop. の警告
- userWordsやguestWordsがテスト間で変更されたまま残ると、同じidや同じ値のデータが何回もリストに追加されることがある
- そのためや
- でmapしたときに同じkeyの要素が複数できて、Reactが「keyが重複している」と警告を出す
- 空配列や変なデータ構造になった場合も、keyがundefinedになって同じ警告が出る
-
Unable to find an element with the text: ... のエラー
- userWordsやguestWordsが空や不正な値になっていると、画面に本来表示されるべきテキストが出なくなる
- そのため、screen.getByText(...)で要素が見つからずエラーになる
- データが重複・壊れていると、同じテキストが複数回描画されて「複数ヒット」エラーになることもある
終わりに
- 個別のテスト実行では問題なく通る
- VSCodeのターミナル、iTerm、GitHub Actionsでエラー内容やエラーの有無がバラバラだった
- そのせいで原因特定が難しくて混乱した
- 1つ1つエラー箇所を絞り込んで、地道に原因を探して解決していくことが大事だと感じた