테스트는 개발에서 필수 과정이며 세 단계로 나눌 수 있다.
Next.js를 테스트하는 것은 리액트나 Express 애플리케이션 등을 테스트하는 것과 다르지 않음
Jest → 단위 및 통합 테스트
Cypress → E2E 테스트
$ yarn add -D jest
모듈을 올바르게 변환할 수 있도록 .babelrc
파일을 열어서 다음 내용을 추가한다.
{
"presets":["next/babel"]
}
export function cutTextToLength(str, maxLength) {
return str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
}
해당함수를 테스트하는 코드를 작성해보자.
import { cutTextToLength } from "../index";
describe("cutTextToLength", () => {
test("Should cut a string that exceeds 10 characters", () => {
const initialString = "This is a 34 character long string";
const cutResult = cutTextToLength(initialString, 10);
expect(cutResult).toEqual("This is a ...");
});
});
Jest 만으로는 리액트 컴포넌트를 테스트할 수 없다.
리액트 컴포넌트를 테스트하려면 컴포넌트를 마운트하고 화면에 렌더링해야함.
$ yarn add @testing-library/react
컴포넌트에 REST API를 호출하는 코드가 있다면, Mock data를 만들어 내용을 채워넣어야 함.
→ 컴포넌트가 화면에 잘 나오는지 확인하는것이 목적이므로 가짜 데이터를 만들어 컴포넌트에 입력을 전달.
react-testing-library의 render
와 screen
메소드를 사용하여 컴포넌트를 화면에 렌더링하고 테스팅 할 수 있음.
Cypress는 웹 브라우저에서 돌아가는 모든 것을 테스트할 수 있음.
$ yarn add -D cypress
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "jest",
"cypress": "cypress run"
},
{
"baseUrl": "http://localhost:3000"
}
cypress가 어디에서 테스트를 실행해야 하는지 알려주는 설정우선 REST API가 제대로 작동하는지 확인할 테스트를 작성
pages/api
에 있는 두 개의 API를 테스트해보자.
import data from '../../data/articles';
export default (req, res) => {
res.status(200).json(data);
};
게시글 목록을 반환하는 APIimport data from '../../../data/articles';
export default (req, res) => {
const id = req.query.id;
const requestedArticle = data.find((article) => article.id === id);
requestedArticle
? res.status(200).json(requestedArticle)
: res.status(404).json({ error: 'Not found' });
};
게시글 ID를 쿼리 인자로 받아서 해당 ID에 해당하는 게시글을 반환하는 APIdescribe("articles APIs", () => {
test("should correctly set application/json header", () => {
cy.request("http://localhost:3000/api/articles")
.its("headers")
.its("content-type")
.should("include", "application/json");
});
test("should correctly return a 200 status code", () => {
cy.request("http://localhost:3000/api/articles")
.its("status")
.should("be.equal", 200);
});
});
해당 API 응답 HTTP 헤더에 content-type=application/json
정보가 있는지 확인하는 테스트코드. 추가로 응답코드가 200인지도 확인하는 테스트 코드도 추가.// API 응답으로 받은 객체 배열을 받으며 각 객체는 반드시 몇가지 속성을 가져야 한다.
test(`should correctly return a list of articles`, (done) => {
cy.request("http://localhost:3000/api/articles")
.its("body")
.each((article) => {
expect(article).to.have.keys("id", "title", "body", "author", "image");
expect(article.author).to.have.keys("id", "name");
expect(article.image).to.have.keys("url", "author");
done();
});
});
// 게시글 ID를 주면 해당 게시글을 읽어오는 API 테스트
test(`should correctly return a an article given an ID`, (done) => {
cy.request("http://localhost:3000/api/article?id=u12w3o0d").then(
({ body }) => {
expect(body).to.have.keys("id", "title", "body", "author", "image");
expect(body.author).to.have.keys("id", "name");
expect(body.image).to.have.keys("url", "author");
done();
}
);
});
// ID에 해당하는 게시글이 없으면 404 에러를 반환하는 테스트코드
test(`should correctly return a 404 status code when an article is not found`, () => {
cy.request({
url: "http://localhost:3000/api/article?id=unexistingID",
failOnStatusCode: false,
})
.its("status")
.should("be.equal", 404);
});
위 테스트 코드도 추가.Cypress는 실제 서버를 대상으로 테스트를 실행하기 때문에 yarn cypress
명령어로 바로 접근이 불가능.
$ yarn add -D start-server-and-test
해당 패키지를 설치해서 해결 가능
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "jest",
"cypress": "cypress run",
"e2e": "start-server-and-test 'yarn build && yarn start' http://localhost:3000 cypress"
},
스크립트 추가yarn e2e
를 명령어를 입력하면 cypress를 통해 E2E 테스트를 할 수 있음.