TDD가 무엇일까?
Test Driven Development 테스트 주도 개발로, 테스트가 개발을 이끌어 나가는 것이다.
기존의 개발 프로세스와 다르게 테스트케이스를 먼저 작성 후, 실제 코드를 개발하여 리팩토링 하는 절차이다.
- 반복 테스트를 이용한 소프트웨어 방법론으로, 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현
- 짧은 개발 주기의 반복에 의존하는 개발 프로세스이며 애자일 방뻐론 중 하나인 eXtream Programming(XP)의 ‘Texst-First’ 개념에 기반을 둔 단순한 설계를 중요시한다.
테스트 종류
프론트엔드 테스트 종류는 Unit테스트, Integration 테스트, E2E테스트로 크게 3가지로 나뉜다고 생각한다.
Unit
컴포넌트 별 기능 단위의 동작을 테스트한다.
함수의 Input과 Output을 검증한다.
가장 쉽고 빠르며 효과가 가장 좋다
Integraion
두 개 이상의 서로 다른 모듈 또는 클래스 간 상호작용 검증
모듈 간 인터페이스 및 데이터 흐름에 대한 검증
(전역 상태관리) 등
E2E (End-To-End)
개발한 결과물(어플리케이션)이 처음부터 끝까지 완벽하게 작동을 검증한다
사용자 입장에서 테스트한다
TDD 개발주기
<Red>단계에서는 실패하는 테스트 코드를 먼저 작성한다.
<Green>단계에서는 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
<Yellow>단계에서는 중복 코드 제거, 일반화 등의리팩토링을 수행한다.
중요한 것은 실패하는 테스트 코드를 작성할 때까지 실제 코드를 작성하지 않는 것과, 실패하는 테스트를 통과할 정도의 최소 실제 코드를 작성해야 하는 것이다.
이를 통해, 실제 코드에 대해 기대되는 바를 보다 명확하게 정의함으로써 불필요한 설계를 피할 수 있고, 정확한 요구 사항에 집중할 수 있다.
TDD를 왜하는데?
애자일에서 설명한 것과 같이 불확실성이 높을 때 “피드백”과 “협력”이 중요하기 때문에 피드백과 협력이 자주 이루어진다면 더 좋은 결과가 나올 수 있다.
애자일 방법론?
신속한 반복 작업을 통해 실제 작동 가능한 소프트웨어를 개발하여 지속적으로 제공하기 위한 소프트웨어 개발 방식
TDD 언제할까?
- 처음해보는 프로그램 주제
- 나에 대한 불확실성이 높은 경우
- 고객의 요구조건이 바뀔 수 있는 프로젝트
- 외부적인 불확실성이 높은 경우
- 개발하는 중에 코드를 많이 바꿔야 된다고 생각하는 경우
- 내가 개발하고 나서 이 코드를 누가 유지보수할지 모르는 경우
- 외부적인 불확실성이 즉, 불확실성이 높을 때 TDD를 하면 된다.
- TDD의 효과
모든 애자일의 실천법은 피드백과 협력을 동시에 증진시킨다.
React에서 Jest와 Testing-library/react로 테스트 코드를 짜보자
test코드를 짜기 위해서는 jest.config.js파일이 필요하다.
현재 next로 작업을 하여 next 공식홈페이지에서 jest 설정 파일을 가지고 와서 변경해주었다.
// jest.config.js
const nextJest = require("next/jest");
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: "./",
});
// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const customJestConfig = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ["node_modules", "<rootDir>/"],
moduleNameMapper: {
"~(.*)$": "<rootDir>/src/$1",
},
testEnvironment: "jest-environment-jsdom",
collectCoverageFrom: [
"src/**/*.tsx",
"!src/**/*.stories.tsx",
"!src/pages/_document.tsx",
],
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
test코드를 작성해보자
import { render, screen } from "@testing-library/react";
import Layout from "~components/Layout";
import "@testing-library/jest-dom";
describe("Layout test", () => {
it("render children", () => {
render(<Layout>test</Layout>);
expect(screen.getByText("test")).toBeVisible();
});
});
위 코드는 레이아웃 컴포넌트를 테스트하는 코드이다.
describe는 테스트의 집합을 뜻하며, it은 한 테스트를 말 할 수 있다.
즉, describe는 레이아웃 컴포넌트 테스트라고 지을 수 있으며, it은 해당 컴포넌트에서 각각의 테스트를 말한다.
render은 테스트할 컴포넌트를 작성해주고, 스크린에 test라는 문구가 잘 보이는지 기대한다는 코드이다.
toBeVisible() 를 사용할 때는 "@testing-library/jest-dom";
에서 가지고오므로 꼭 import를 해주어야한다.
만약 클릭이벤트가 필요하다면 userEvent.click(screen.getByText("퀴즈풀기"));
위와 같이 userEvent의 click을 사용하면 된다.
네트워크 통신이 필요한 컴포넌트들은 목업 서버와 목업 데이터를 이용하자!