수업 마지막주가 시작된날.
기능없이 테스트를 하는 방식(ttd)
테스트
:마우스로 클릭하는것등을 대신해주는것.(API요청등)
이 대신해주는 코드를 만드는것이 테스트코드
모든 기능을 테스트 후 배포를 한다. => 잘 사용하는 중에 이후 기능을 추가를 하기로 하고 어떤 기능을 추가한다.
물론 이 과정에서 추가할 기능의 테스트를 하고, 그후 이 기능을 추가하여 배포를 (업데이트배포)한다.
=> 이후 사용하다가 관련된 다른 기능에서 에러가난다.(물론 추가한 기능은 테스트를 완료하고 추가했으니 문제가 없다. 다만 이 기능들과 관련된 어떤 부분에서 문제가 생겼다
==> 그럼 추가된 기능과 연결된 문제인것인데 어디서 문제가 생겼는지 알 수 없다.
과연 이 에러만 있을까
따라서 기능 하나를 만들때(추가할때) 모든 기능들을 다 테스트 해봐야한다.
테스트 코드가 필요한이유!!
==> 이 모든 기능을 수동으로 테스트 해보기에는 너무 많다.
따라서 서비스 규모가 커질수록 더 테스트를 자동으로 돌려주게하는 테스트 코드가 중요하다.
jest설치
yarn add --dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
=> 네가지가 설치되는데 testing=library/react는
jest.config.ts 라는 파일을 만들고 설정 파일을 복사해 붙여넣는데
해당 설정파일은 next 버전에 맞는 버전이기에 얘도 버전을 12.1.0로 수정하고 다시 yarn install을 한다.
https://nextjs.org/docs/testing#jest-and-react-testing-library
여기를 참고!!!
추가 :
moduleDirectories: ["node_modules", "<rootDir>/"] ```,
"test": "jest"
로 yarn test시에 jest가 실행되게 실행 명령어도 추가
jest를 eslint를 함께 사용하기위해서는 추가해줘야 할 내용이 있습니다.
.eslintrc.js 파일로 들어가 아래 내용으로 바꿔주세요!
plugins: ["react","jest/globals"],
"scripts": { "test": "jest", "test:watch": "jest --watch" } test:watch는 소스코드를 고칠때마다 jest가 실행되길 원하신다면 추가해주시면 됩니다. 만일 추가하지 않으신다면, 원할때마다 `yarn test` 를 입력하셔서 jest를 실행해주셔야 합니다.
UI테스트
// UI테스트 하기export default function JestUnitTestPage(): JSX.Element { return ( <> <div>철수는 13살 입니다</div> 철수의 취미 입력하기: <input type="text" /> <button>철수랑 놀러가기</button> </> ); }
>
>``
import JestUnitTestPage from "../../pages/section33/33-02-jest-unit-test";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
>
it("내가 원하는데로 그려지는지 테스트 하기", () => {
render(<JestUnitTestPage />); // 가상돔에 그리기
>
const myText = screen.getByText("철수는 13살 입니다");
expect(myText).toBeInTheDocument(); // 돔안에 그려져있는지 기대(그려져 있는지를 봄)
const myText2 = screen.getByText("철수의 취미 입력하기:");
expect(myText2).toBeInTheDocument();
const myText3 = screen.getByText("철수랑 놀러가기");
expect(myText3).toBeInTheDocument();
});
>
실무에서는 일단 필요한 부분만 테스트를 돌리고, 그중에서 걸리는 것을 따로 또 테스트 코드를 작성하여 돌리는 방식이다.
그럼 일일히 텍스트등을 다 직접 적어서 테스트 코드를 짜야하나?
으로 찍어서 비교한다.
import JestUnitTestPage from "../../pages/section33/33-03-jest-unit-test-snapshot"; import { render } from "@testing-library/react"; import "@testing-library/jest-dom"; it("내가 원하는데로 그려지는지 테스트 하기", () => { const result = render(<JestUnitTestPage />); // 가상돔에 그리기 expect(result.container).toMatchSnapshot(); // 스냅샷이랑 다른게있는지 비교, 없으면 사진을 찍어 만듬. // 처음 명령어는 yarn test로 없으면 스냅샷을 찍어둠.. 이후 스냅샷 업데이트 된것으로 찍으려면 yarn test -u });
// 테스트 코드는 정답을 테스트 하는것이 아니라 뭔가 바뀌었을때 알려주는 용도 라고 이해하면 될 듯.
APi테스트해보기
실제 벡엔드가 있어야 할 수 있는것. 따라서 이렇게되면 벡엔드에 의존할 수 밖에 없고, 기능 하나 추가할때마다 그 많은 api를 다 요청하는것은 비효율적.
따라서 모킹을 이용. => 가짜로 만들기.
mocking은 결국 api를 가짜로 만들어야 하기때문에 각각 라이브러리마다 제공해주는 기능이 있다.
-->yarn add -D msw cross-fetch next-router-mock
Mocking
화면 랜더링
input창들에 값입력 => fireEvent사용
등록하기 버튼 클릭 => fireEvent사용
뮤테이션 날리기 => 가짜 api를 먼저 만들고 실행.(뮤테이션을 날리면 이 가짜가 실행됨. 그리고 result에 결과를 담음.
등록된 페이지로 이동. => router.push로 이동됨.
==> 최종적 검증 해야하는 부분은 마지막 router.push(/boards/게시물아이디) => 이 부분.
MSW사용: mock-service-worker 설치,cross-fetch 설치
yarn add cross-fetch --dev
yarn add msw --dev
yarn add next-router-mock --dev
위의 api 파일을 사용하기 위해서 서버를 셋팅할 수 있는 js 파일을 동일한 디렉토리 안에 새로 생성 =>
import { setupServer } from "msw/node";
import { apis } from "./apis";
>
// 모킹 데이터를 가짜 서버로 돌릴 수 있도록 설정
export const server = setupServer(...apis);
jest가 실행될 때마다 서버를 그때그때마다 수동으로 작동시키기는 매우 비효율적이므로
jest가 자동으로 서버를 실행시킬 수 있도록 설정이 필요합니다.
상위 디렉토리, jest.config.js와 동일한 경로의 디렉토리 안에 jest.setup.js 파일을 생성한 후
서버를 실행시키는 코드를 새로 추가합니다.
import { server } from "./src/commons/mocks"; beforeAll(() => server.listen()); afterAll(() => server.close());
jest가 서버를 자동으로 실행시킬 수 있도록, jest.config.js에서
jest.setup.js가 서버를 실행시켜주는 파일임을 명시해줘야 합니다.// jest.config.js const customJestConfig = { ... ... ... // jest 실행시마다 실행되는 셋팅 파일 setupFilesAfterEnv: ["./jest.setup.js"], };
eslint가 jest를 감지할 수 있도록
eslintrc.js의 env탭에 jest를 추가해줍니다.// eslintrc.js module.exports = { env: { browser: true, es2021: true, jest: true, }, ... ... }
단일테스트: 기능하나를 테스트
통합 // : 기능 여러개 묶어서 테스트
E2E테스트: 사이프레스 라는 도구를 사용해 하는 테스트(next에서 cypress사용하기)
yarn add --dev cypress
TTD => 기능을 만들기 전에 테스트코드 먼저 만들기
Test-Driven-Development , 테스트 주도 개발을 의미합니다. 보통의 개발 과정은 다음과 같습니다. 요구 사항을 정의하고, 디자인이 나오고, 이를 토대로 실제 코드를 작성 하고 테스트를 진행합니다.
하지만 TDD는 테스트 코드를 먼저 작성하고 그 후에 테스트를 통과하기 위한 최소한의 실제 코드를 작성합니다. 그 다음에 코드를 리팩토링합니다.
그리고 가장 중요한 API모킹!!!