Reactのテストコードの練習をchatGPT4に作らせた
コンポーネントの表示テスト
実装コード (App.js):
import React from "react";
function App() {
return (
<div>
<h1>Hello, World!</h1>
</div>
);
}
export default App;
テストコード (App.test.js):
import React from "react";
import { render } from "@testing-library/react";
import App from "./App";
// このテストは、Appコンポーネントが正しく表示されることを確認します。
// `render`関数を使ってコンポーネントをレンダリングし、`getByText`を使って、
// 期待されるテキストが表示されているかどうかをチェックします。
test("renders App component", () => {
const { getByText } = render(<App />);
const linkElement = getByText(/Hello, World!/i);
expect(linkElement).toBeInTheDocument();
});
コンポーネントのpropsテスト
実装コード (Greeting.js):
import React from "react";
function Greeting(props) {
return <p>Hello, {props.name}!</p>;
}
export default Greeting;
テストコード (Greeting.test.js):
import React from "react";
import { render } from "@testing-library/react";
import Greeting from "./Greeting";
// このテストは、Greetingコンポーネントが正しく表示され、渡されたpropsを使用していることを確認します。
// `render`関数を使ってコンポーネントをレンダリングし、`getByText`を使って、期待されるテキストが表示されているかどうかをチェックします。
test("renders Greeting component with props", () => {
const { getByText } = render(<Greeting name="John" />);
const greetingElement = getByText(/Hello, John!/i);
expect(greetingElement).toBeInTheDocument();
});
イベントハンドラのテスト
実装コード (Button.js):
import React from "react";
function Button(props) {
return <button onClick={props.onClick}>Click me!</button>;
}
export default Button;
テストコード (Button.test.js):
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import Button from "./Button";
// このテストは、ButtonコンポーネントのonClickイベントハンドラが正しく動作することを確認します。
// `fireEvent`を使って、クリックイベントをシミュレートします。
test("triggers onClick event handler when clicked", () => {
const handleClick = jest.fn();
const { getByText } = render(<Button onClick={handleClick} />);
const buttonElement = getByText(/Click me!/i);
fireEvent.click(buttonElement);
expect(handleClick).toHaveBeenCalledTimes(1);
});
useStateフックのテスト
実装コード (Counter.js):
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;
テストコード (Counter.test.js):
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import Counter from "./Counter";
// このテストは、CounterコンポーネントのuseStateフックが正しく動作することを確認します。
// `fireEvent`を使って、クリックイベントをシミュレートし、カウントが増加することをチェックします。
test("increments count when button is clicked", () => {
const { getByText } = render(<Counter />);
const buttonElement = getByText(/Increment/i);
fireEvent.click(buttonElement);
expect(getByText(/Count: 1/i)).toBeInTheDocument();
});
useEffectフックのテスト
実装コード (Title.js):
import React, { useEffect } from "react";
function Title() {
useEffect(() => {
document.title = "React Testing";
return () => {
document.title = "React App";
};
}, []);
return <div>Testing useEffect</div>;
}
export default Title;
テストコード (Title.test.js):
import React from "react";
import { render, cleanup } from "@testing-library/react";
import Title from "./Title";
// このテストは、TitleコンポーネントのuseEffectフックが正しく動作することを確認します。
// テスト後にcleanup関数を実行して、コンポーネントをアンマウントします。
afterEach(cleanup);
test("updates document title on mount and unmount", () => {
render(<Title />);
expect(document.title).toBe("React Testing");
cleanup();
expect(document.title).toBe("React App");
});
useContextフックのテスト
実装コード (ThemeContext.js):
import React, { createContext, useContext } from "react";
const ThemeContext = createContext("light");
export function useTheme() {
return useContext(ThemeContext);
}
export function ThemeProvider({ children }) {
return (
<ThemeContext.Provider value="dark">{children}</ThemeContext.Provider>
);
}
実装コード (ThemedComponent.js):
import React from "react";
import { useTheme } from "./ThemeContext";
function ThemedComponent() {
const theme = useTheme();
return <div>Current theme: {theme}</div>;
}
export default ThemedComponent;
テストコード (ThemedComponent.test.js):
import React from "react";
import { render } from "@testing-library/react";
import { ThemeProvider } from "./ThemeContext";
import ThemedComponent from "./ThemedComponent";
// このテストは、ThemedComponentがuseContextフックを使って正しくテーマを取得できることを確認します。
// ThemeProviderコンポーネントを使って、テスト用のコンテキストプロバイダを作成します。
test("renders with correct theme from context", () => {
const { getByText } = render(
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
expect(getByText(/Current theme: dark/i)).toBeInTheDocument();
});
React.memoをテスト
実装コード (ExpensiveComponent.js):
import React from "react";
function ExpensiveComponent({ value }) {
console.log("Rendering ExpensiveComponent...");
return <div>Value: {value}</div>;
}
export default React.memo(ExpensiveComponent);
実装コード (ParentComponent.js):
import React, { useState } from "react";
import ExpensiveComponent from "./ExpensiveComponent";
function ParentComponent() {
const [value, setValue] = useState(0);
const [otherValue, setOtherValue] = useState(0);
return (
<div>
<ExpensiveComponent value={value} />
<button onClick={() => setValue(value + 1)}>Update value</button>
<button onClick={() => setOtherValue(otherValue + 1)}>
Update other value
</button>
</div>
);
}
export default ParentComponent;
テストコード (ExpensiveComponent.test.js):
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import ParentComponent from "./ParentComponent";
// このテストは、ExpensiveComponentがReact.memoによって正しくメモ化されていることを確認します。
// コンソールログによるレンダリングの追跡を行い、他の値が更新された場合にExpensiveComponentが再レンダリングされないことを確認します。
test("ExpensiveComponent is not re-rendered when otherValue changes", () => {
const { getByText } = render(<ParentComponent />);
const updateValueButton = getByText(/Update value/i);
const updateOtherValueButton = getByText(/Update other value/i);
const logSpy = jest.spyOn(console, "log").mockImplementation();
fireEvent.click(updateOtherValueButton);
expect(logSpy).not.toHaveBeenCalledWith("Rendering ExpensiveComponent...");
fireEvent.click(updateValueButton);
expect(logSpy).toHaveBeenCalledWith("Rendering ExpensiveComponent...");
});
カスタムフックをテスト
実装コード (useCounter.js):
import { useState } from "react";
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
function increment() {
setCount(count + 1);
}
return { count, increment };
}
export default useCounter;
実装コード (CounterWithCustomHook.js):
import React from "react";
import useCounter from "./useCounter";
function CounterWithCustomHook() {
const { count, increment } = useCounter(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default CounterWithCustomHook;
テストコード (useCounter.test.js):
import { renderHook, act } from "@testing-library/react-hooks";
import useCounter from "./useCounter";
// このテストは、useCounterカスタムフックが正しく機能することを確認します。
// `renderHook`と`act`を使って、フックの内部状態を検証します。
test("useCounter works correctly", () => {
const { result } = renderHook(() => useCounter(0));
expect(result.current.count).toBe(0);
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
すげーなと。
この記事が気に入ったらサポートをしてみませんか?