banilla JavaScript / pnpm + Vite + Vitest + v8(coverage)
이야기가 길어질 수 있으니 차이점만 궁금한 사람은 🔽 아래로
나는 JavaScript 기초 강의를 들으면서 배운대로 테스트 코드도 같이 짜보며 차근차근 공부하고 있어서 모르는 게 참 많다.
그만큼 나중에 스스로 기억하기 쉽고, 나와 같이 비슷하게 제로베이스로 시작하는 모두에게 도움을 주고자 내가 겪은 문제와 그걸 해결한 방법 그리고 왜 문제가 있었는지를 전부 적어볼 예정이다.
Vitest는 Jest와 호환이 매우 잘 되지만, 최대한 Vitest에서 일어나는 error로 생각하고 해결하기 때문에 절차가 다를 수 있으니 참고 바란다. 처음 겪는 error들을 보여주기 때문에 완벽하지 않을 수 있다. 성장 과정으로 봐주었으면 좋겠다!
error가 뜬 테스트는 굉장히 간단했다. 내장 함수 split을 써서 배열로 반환했고, console.log()로는 쉽게 끝냈고 테스트 코드를 작성했다.
`built-inQuiz0.js`
// 2. 사용자들의 id를 잘라내어 각각의 id를 배열로 보관
const ids = "user1, user2, user3, user4";
export { ids };
`built-inQuiz0.test.js`
import { test, expect } from "vitest";
import { ids } from "../built-inQuiz0";
test("각각의 id를 배열로 보관하기", () => {
expect(ids.split(", ")).toBe(["user1", "user2", "user3", "user4"]);
});
언뜻 보기엔 뭐가 다른 거냐고 생각할 수 있다. (내가 그랬다.)
친절하게 deep Equality를 위해선 `toBe()`대신 `toStrictEqual()`을 쓰라는 메세지 덕분에 수정 후 pass될 수 있었다.
항상 `expect().toBe()`만으로 테스트를 했던 나는 호기심이 생겼다!
`toBe`,`toEqual`과 `toStrictEqual`
Vitest의 공식 홈페이지를 많이 참고했다.
toBe
`toBe`는 기본 데이터(primitive)가 동일한지 또는 객체가 같은 참조(Reference)를 공유하는지를 확인하는 데 사용된다!
`expect(Object.is(3, 3)).toBe(true)`를 호출한 것이랑 동등하다.
객체가 동일하지 않지만 구조가 동일한지 확인하려면 `toEqual`을 사용할 수 있다.
import { expect, test } from 'vitest'
const stock = {
type: 'apples',
count: 13,
}
test('stock has 13 apples', () => {
expect(stock.type).toBe('apples')
expect(stock.count).toBe(13)
})
test('stocks are the same', () => {
const refStock = stock // same reference
expect(stock).toBe(refStock)
})
JavaScript에서 부동 소수점 연산은 정확한 값을 보장하지 않을 수 있기 때문에, 부동 소수점 수의 비교를 정확하게 하기 위해서는 `toBeCloseTo`를 사용하는 것이 좋다고도 안내되어있다.
toEqual
`toEqual`은 실제 값이 받은 값과 같거나, 만약 객체인 경우에는 구조가 동일한지를 확인하는 단언문이다.
두 객체의 구조와 값만을 비교하며, 객체의 타입은 신경쓰지 않는다.
재귀적으로 비교된다.
재귀적으로 비교된다?
객체의 속성들을 깊이 있는 구조까지 비교한다는 의미. 객체가 다른 객체를 포함하고 있을 때, 그 내부의 객체들도 `toEqual`로 비교 대상이 된다.
import { expect, test } from 'vitest';
const stockBill = {
type: 'apples',
count: 13,
};
const stockMary = {
type: 'apples',
count: 13,
};
test('stocks have the same properties', () => {
expect(stockBill).toEqual(stockMary);
});
test('stocks are not the same', () => {
expect(stockBill).not.toBe(stockMary);
});
toStrictEqual
`toStrictEqual`은 실제 값이 받은 값과 동일하거나, 객체인 경우 동일한 구조를 가지며 (재귀적으로 비교), 두 값이 동일한 타입인지 확인하는 단언문이다.
`toEqual`과의 차이점
조금 더 엄격한 Equal이라고 보면 된다.
1. `undefined`속성을 가진 키는 확인된다. 예를 들어, `{a: undefined, b: 2}`는 `.toStrictEqual`을 사용할 때 {b: 2}와 일치하지 않는다.
2. 배열 내의 공백(사라진) 요소가 확인된다. 예를 들어, [, 1]는 `.toStrictEqual`을 사용할 때 [undefined, 1]와 일치하지 않는다.
3. 객체의 타입까지 확인하며, 클래스 인스턴스와 리터럴 객체를 구별한다. 예를 들어, a와 b라는 필드를 가진 클래스 인스턴스는 a와 b 필드를 가진 리터럴 객체와 일치하지 않는다.
import { expect, test } from 'vitest'
class Stock {
constructor(type) {
this.type = type
}
}
test('structurally the same, but semantically different', () => {
expect(new Stock('apples')).toEqual({ type: 'apples' })
expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' })
})
결론
내가 기존에 작성한 `toBe`는 참조값과 원시타입을 체크하기 때문에 오류가 떴던 것이다.
`toEqual`을 쓴 경우에도 pass가 되지만 엄격한 비교를 위해선 `toStrictEqual`을 습관화하는 것이 좋겠다.
이걸 통해서 코어 자바스크립트 데이터 타입 부분이 생각난다 🤔
객체나 배열을 비교할 땐 `toBe`는 지양해야겠다.
ChatGPT🤖
'Test Code' 카테고리의 다른 글
Vitest에서 모의 타이머(mocking timers)로 시간 출력 테스트하기 (0) | 2023.08.17 |
---|---|
What is Vitest? Vite와 함께 알아보자 + 코드 커버리지 확인 (0) | 2023.08.09 |
New 맥북에서 pnpm + Vite 환경 + Vitest 구축하기 (2) | 2023.08.05 |