06
06

전형적인 릴리즈 15분 27초 전 모습.jpge

1. 왜 필요한가?

  • 눈으로 다 확인할 수 있는 프론트 기능들이지만, 모든 부분을 완벽하게 테스트하기는 쉽지 않다.
  • 그렇게 모든 상황을 다 테스트 하더라도, 시간이 너무 오래 걸린다.
  • 프로젝트의 사이즈가 커지면 커질수록, 협업을 하게 되는데, 동료 개발자가 작업했던 부분을 작업하게 되는 경우가 종종 생긴다. 이때, 의도되지 않은 버그가 있다면 그대로 배포될지도 모른다. 이때, 테스트를 통해 검사할 수 있다. => 실무에서는 이전버전에서 이미 배포된 기능의 코드를 이번 버전에서 고칠 경우가 생기는데 이미 이전 버전에서 Qa가 끝난 부분이기 때문에 자세히 보지 않는 경우가 있다. 이럴 경우 치명적인 버그가 배포될 경우가 생기기 쉽다.
  • 가장 중요한 것은, 릴리즈 당일, 팀원들과 가족 같은 분위기를 형성하게 될 수 있는 상황을 미연에 방지한다.

2. 유닛 테스트

  • 작은 단위(컴포넌트 정도)의 기능동작을 확인하는 테스트
    • 컴포넌트가 잘 렌더링 되는가?
    • 함수는 올바르게 동작하는가?
    • state를 올바르게 사용하고, 올바르게 setState 하는가?

3. 통합 테스트

  • 프로젝트가 전체적으로 올바르게 동작하는지를 확인하는 테스트
    • 수많은 컴포넌트들이 서로 잘 동작하며 각각의 역할을 올바르게 하여 정상적으로 동작하는가?
    • DOM 이벤트가 올바르게 화면을 변화시켜 주는가?

4. Jest

자바스크립트 코드 테스트 자동화 Tool 중 대표적인 Jest

  • 가장 단순한 테스트 툴, 기본적인 설정을 해 줄 필요가 없어서 간단하다.
  • 스냅샷 기능을 지원하여, 오브젝트가 변경되면 에러를 보여줄 수 있다. -> 렌더링 된 컴포넌트의 변경도 체크할 수 있다.
  • 테스트 코드는 작업물과 완전히 분리되어 있다.
  • API도 -coverage 옵션을 사용해 커버리지를 확인할 수 있도록 되어 있어, 매우 단순하다.

5. 실전 테스트

  • 먼저 프로젝트를 생성한다. (cra을 해도 테스트해 보기는 괜찮다! 다 깔려있다! 만약, yarn init 했다면 babel도 설치해 주자 yarn add --dev babel-jest @babel/core @babel/preset-env)
  • 생성한 프로젝트에 yarn add -D jest
  • package.json에 script에 test 명령어를 넣어준다.
{
  "name": "jest-test",
  "version": "1.0.0",
  "main": "index.ts",
  "license": "MIT",
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^29.5.0"
  }
}
  • index.js에 함수를 만들어 준다. 나는 NaN을 판별해 주는 함수를 만들 것이다.
export const checkNaN = (value) => {
  return !Object.is(value, NaN) ? "참" : "거짓";
};
  • 그리고, index.test.js파일을 test 폴더에 만들어서, jest가 검사할 수 있도록 한다.
  • 그리고 몇 가지 검사를 한다. 방법은 test('로그', 콜백함수)의 형태로 작성한다. 아래는 예시이다.
import { checkNaN } from "../index";

test("1번 : 1은 NaN이 아니다!", () => expect(checkNaN(1)).toBe("참"));
test("2번 : 3 + 6은 NaN이 아니다!", () => expect(checkNaN(3 + 6)).toBe("참"));
test("4번 : 10 / abc은 NaN이 아니다!", () => expect(checkNaN(10 / "abc")).toBe("거짓"));
  • 결과를 보기 위해 yarn test를 입력하면?

야호! 100점

6. toBe

  • 위에서 사용한 toBe 함수는 완전히 같은 요소인지를 검사한다.
  • Object일 경우 같은 메모리 참조가 아니기 때문에 toBe로 검사할 수 없다.
  • 비슷한 toBe시리즈 함수로는 toBeTruthy, toBeFalsy, toBeNull이 있다. 사용법은 똑같으니 생략

7. toEqual

  • Object형태까지 구분이 가능하다.
const getFriend = (name, age) => {
  return {
    name,
    age,
  };
};

test("내 친구의 이름은 hendrix, 나이는 20이야.", () => expect(getFriend("hendrix", 20)).toBe({ name: "hendrix", age: 20 }));
  • 간단하게 친구 정보를 불러오는 함수이다.

땡! 심지어 deep equality하게 검사해야 통과한다고, toStrictEqual을 사용하란다. 친절 그잡채

test("내 친구의 이름은 hendrix, 나이는 20이야.", () => expect(getFriend("hendrix", 20)).toStrictEqual({ name: "hendrix", age: 20 }));

코드를 수정한 이후 성공!

  • 여기서 toEqual과 toStrictEqual의 차이는 toStrictEqual가 더 엄격하게 undefined도 허용하지 않는 함수이다. 

8. 여담

  • 부트캠프를 진행하면서 보았던 문제 형식의 스프린트는 이런 식으로 만드는 구나를 깨달았다. (그럼 계산을 위한 코드도 어딘가에 공식처럼 적혀 있다는 것인데... 그거 뜯어보면 전부 간단하게 해결할 수 있다는 것인데... 그걸 찾는다면 이미 개발 실력이 늘어날 듯하다)
  • 한 발자국 더 나아가면, 저런 테스트 코드를 캡슐화하여 잘 숨겨놓고, 더 어렵게, 그리고 더 엄격하게 검사하는 코드도 넣으면 참 좋은 스프린트를 만들 수 있지 않을까?라는 생각도 들지만 이미 부트캠프를 나온 지 1년 6개월은 넘어서 의미가 없다 흑흑,
  • 실무에서는 테스트 코드를 작성할 수 있을까?라고 한다면 스타트업의 경우 거의 불가능... 하지 않을까 싶다. 규모가 그리 크지 않고, 프론트 개발팀 구성원이 몇 명 없는 경우, 항상 개발시간에 쫓겨가다 보면, 데드라인 맞추기도 급급해서 테스트 코드까지 작성할 시간이 항상 부족하다. 조금만 여유가 있다면, 오히려 Qa 시간도 줄이고, 탄탄한 코드로 이후 유지보수가 뛰어나다는 생각을 운영진도 해 줬으면...!이라고 생각만 하고 있다 흑흑.
  • 하지만 짬날 때마다 테스트 코드를 작성해 놓으면 충분히 도움이 될 것이다. 지금 업무로 진행하는 프로젝트의 특성(기획이 한 번에 픽스되어 나오지 않고, 조금씩 쌓이고 쌓이고 하는 구조) 덕분에 같은 작업자들끼리 기능적으로 꼬이는 부분이 있었는데, 테스트 코드가 있다면 충분히 커버될 것이라고 생각했다.
COMMENT