第155章:練習:カウンターアプリのテストを書いてみる
この章では、**カウンター(+1/-1/リセット)を例にして、「画面に出るものを確認するテスト」**を書いていくよ〜😊✨ ポイントは ユーザー目線(ボタン押したら数字が変わる?)でチェックすること!👀💡
この章のゴール🎯
- ✅ カウンター部品を render して表示を確認できる
- ✅ ボタンをクリックして 数が変わることをテストできる
- ✅ テストの基本形 AAA(Arrange / Act / Assert) が分かる🙆♀️
テストの流れを図でイメージしよ🧠✨
1) カウンター部品を用意しよう🧩✨
src/Counter.tsx を作って、こうしてね👇(すでにある人は読み替えでOK!)
import { useState } from "react";
type CounterProps = {
initial?: number;
};
export default function Counter({ initial = 0 }: CounterProps) {
const [count, setCount] = useState<number>(initial);
return (
<div>
<h2>Counter</h2>
{/* テストしやすいように label を付けるよ */}
<output aria-label="count">{count}</output>
<div style={{ display: "flex", gap: 8, marginTop: 12 }}>
<button type="button" onClick={() => setCount((c) => c + 1)}>
+1
</button>
<button type="button" onClick={() => setCount((c) => c - 1)}>
-1
</button>
<button type="button" onClick={() => setCount(0)}>
リセット
</button>
</div>
</div>
);
}
2) テスト環境チェック🧰✨(入ってなければ入れる)
第152章で入れてる想定だけど、もしまだなら(PowerShellで)👇
npm i -D vitest jsdom @testing-library/react @testing-library/jest-dom
package.json にテストコマンドも用意しよう📝
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"test": "vitest"
}
}
3) vite.config.ts にテスト設定を追加⚙️✨
プロジェクト直下の vite.config.ts をこうしてね👇
(すでに test: があるなら追記でOK!)
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
environment: "jsdom",
globals: true,
setupFiles: "./src/setupTests.ts",
},
});
4) setupTests.ts を作る🧪✨(便利な matcher を使う)
src/setupTests.ts を作って、これ👇
import "@testing-library/jest-dom/vitest";
これで toBeInTheDocument() とか toHaveTextContent() が使えるよ〜🥳💕
5) いよいよテストを書くよ!🧪🔥(第155章のメイン)
src/Counter.test.tsx を作って、これを書こう👇
import { render, screen, fireEvent } from "@testing-library/react";
import Counter from "./Counter";
describe("Counter", () => {
test("初期表示は 0", () => {
// Arrange
render(<Counter />);
// Assert
const output = screen.getByLabelText("count");
expect(output).toHaveTextContent("0");
});
test("+1 を押すと 1 になる", () => {
// Arrange
render(<Counter />);
// Act
const plusButton = screen.getByRole("button", { name: "+1" });
fireEvent.click(plusButton);
// Assert
expect(screen.getByLabelText("count")).toHaveTextContent("1");
});
test("+1 を2回押して、-1 を押すと 1 になる", () => {
// Arrange
render(<Counter />);
// Act
const plusButton = screen.getByRole("button", { name: "+1" });
const minusButton = screen.getByRole("button", { name: "-1" });
fireEvent.click(plusButton);
fireEvent.click(plusButton);
fireEvent.click(minusButton);
// Assert
expect(screen.getByLabelText("count")).toHaveTextContent("1");
});
test("リセットを押すと 0 に戻る", () => {
// Arrange
render(<Counter />);
// Act
const plusButton = screen.getByRole("button", { name: "+1" });
const resetButton = screen.getByRole("button", { name: "リセット" });
fireEvent.click(plusButton);
fireEvent.click(plusButton);
fireEvent.click(resetButton);
// Assert
expect(screen.getByLabelText("count")).toHaveTextContent("0");
});
});
6) テストを実行しよう🏃♀️💨
npm run test
うまくいくと、緑のチェック✅が出るよ〜!🥰✨
よくあるつまずき🐣💦(すぐ直るやつ!)
-
😵
document is not defined→vite.config.tsのenvironment: "jsdom"が入ってるか見てね! -
😵
toHaveTextContent is not a function→src/setupTests.tsが作れてるか、setupFilesのパスが合ってるか確認!
ミニ課題💖(できたら天才👏✨)
- 🧠
initialを使って 初期値が 10 のとき 10 が出るテストを書いてみて! ヒント:render(<Counter initial={10} />)だよ😺
次の第156章では、もっとリアルな操作ができる @testing-library/user-event を使って、テストがさらに「人間っぽく」なるよ〜👩💻💗