JavaScript에서 내장객체를 사용하는 퀴즈를 풀게 되었다.
1초에 한 번씩 날짜를 포함한 시간을 출력하는 문제이다. 제시받은 `setInteval()`메서드를 사용하면 된다.
setInterval(callback, delay);
// callback : 지정된 시간 간격마다 실행될 콜백 함수
// delay : 콜백 함수가 실행되기 전의 시간 간격을 밀리초 단위로 지정함.
const intervalID = setInterval(whatTime, 1000);
function whatTime() {
const now = new Date();
console.log(now);
}
setInterval()
Window 및 Worker 인터페이스에서 제공되는 `setInterval()`메서드는 각 호출 사이에 고정된 시간 지연으로 함수를 반복적으로 호출하거나 코드 스니펫을 실행한다.
➡️ 일정한 시간 간격으로 원하는 작업을 반복적으로 수행할 수 있다.
사용 후 `clearInterval()`함수를 호출하여 반복 작업을 중지할 수 있다. 웹 애플리케이션에서 업데이트나 상태 변경을 주기적으로 감지하는 데 유용하게 사용할 수 있음.
// intervalID를 사용하여 반복 작업 중지
clearInterval(intervalID);
`console.log()`로 출력하는 것은 쉬웠다.
다만 이걸 테스트 코드로 옮기자니 막막해졌다. 1초마다 시간이 계속 출력되는데 어떻게 테스트하지? 🤔💭
Vitest로 테스트를 해야하기 때문에 Vitest 공식 홈페이지를 참고했다.
vi.useFakeTimers()
이 메서드는 *모의 타이머(mocking timers)를 활성화하는데 사용된다.
모의 타이머란, 테스트 환경에서 `setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `nextTick`, `setImmediate`, `clearImmediate` 및 Date와 같은 타이머와 관련된 함수를 모의화하여 가짜 시간 제어를 할 수 있는 기능이다.
테스트 시간을 조작하거나 타이머 동작을 제어하여 테스트 시나리오를 만들거나 시간 기반 동작을 테스트할 때 유용하다.
즉, `vi.useFakeTimers()`를 호출하면 이후의 타이머 관련 함수 호출은 모의화되어 가짜 시간을 사용하게 된다.
테스트 환경에서 타이머 동작을 실제로 실행하지 않고 시간을 미리 설정하거나 조작하여 테스트를 수행할 수 있게 된다.
`setInterval()`은 `clearInterval()`로 초기화해주어야 하는 것 처럼, `vi.useFakeTimers()`는 `vi.useRealTimers()`를 호출하여 원래의 타이머 동작으로 복원할 수 있다. 이전에 실행된 모든 타이머는 복원되지 않는다.
vi.?
`vi`는 Vitest 테스트 프레임워크에서 제공하는 기능을 사용하기 위한 객체다. Vitest는 테스트 코드를 작성하고 실행하기 위한 도구로서, `vi` 객체를 통해 다양한 기능을 제어하고 테스트 환경을 설정할 수 있다.
`vi` 객체는 Vitest의 일부로서, 다양한 메서드와 속성을 포함하고 있다. 테스트 코드에서 `import`를 사용하여 가져와서 사용할 수 있다.
vi.advanceTimersByTime()
지정한 밀리초(ms) 후에 종료되는 메서드. 이 메서드를 사용하면 테스트에서 시간을 빠르게 흐르게 하거나 조작하여 특정 시간 동안의 동작을 테스트할 수 있다.
예를 들어 다음 코드는 1, 2, 3을 출력하고 예외를 발생시키지 않는다.
let i = 0;
setInterval(() => console.log(++i), 50);
vi.advanceTimersByTime(150);
위 코드는 `setInterval()`을 사용하여 50 밀리초마다 숫자를 증가시키며 출력하는 예제다.
풀이 과정
// clock.js
function startClock() {
const intervalID = setInterval(whatTime, 1000);
function whatTime() {
const now = new Date();
console.log(now);
}
}
export { startClock };
import { test, expect, vi } from "vitest";
import { startClock } from "../../built-in/clock";
test("prints the current time every second", async () => {
// 모의 타이머 활성화하기
vi.useFakeTimers();
// console.log 대신 결과를 저장할 배열 사용
const consoleOutput = [];
// console.log를 재정의하여 출력을 배열에 저장
console.log = message => {
consoleOutput.push(message);
};
// startClock() 함수 호출, setInterval()을 사용하여 주어진 간격마다 시간을 출력하는 작업을 반복.
// clockPromise는 이 작업이 완료될 때까지 기다리기 위해 사용될 프로미스이다.
// vi.advanceTimersByTime() 메서드를 호출하여 시간을 1000밀리초(1초)만큼 빠르게 흐르게 함.
// 이렇게 함으로써 테스트 코드는 시계가 1초에 한 번씩 작동하는지를 테스트할 수 있다.
const clockPromise = startClock();
vi.advanceTimersByTime(1000);
await clockPromise;
// 예상 출력과 실제 출력을 비교하여 테스트 진행
expect(consoleOutput).toEqual([
new Date().toString()
]);
// 모의 타이머 복원
vi.useRealTimers();
});
But. 오류 발생 😥
AssertionError: expected [ 2023-08-16T14:49:09.537Z ] to deeply equal [ Array(1) ]
- Expected
+ Received
Array [
- "Wed Aug 16 2023 23:49:09 GMT+0900 (GMT+09:00)",
+ 2023-08-16T14:49:09.537Z,
]
예상 출력 Expected 과 실제 출력 Received 의 형식이 다르기 때문에 생긴 문제.
예상 출력은 문자열 형태의 날짜와 시간을 포함하고 있지만, 실제 출력은 JavaScript의 `Date`객체이다.
두 형식을 통일시키기 위해 동일한 형태로 변환해야 했다.
import { test, expect, vi } from "vitest";
import { startClock } from "../../built-in/clock";
test("prints the current time every second", async () => {
vi.useFakeTimers();
const consoleOutput = [];
console.log = (message) => {
consoleOutput.push(message);
};
const clockPromise = startClock();
vi.advanceTimersByTime(1000);
await clockPromise;
// 예상 출력을 문자열로 변환
const expectedOutput = [new Date().toString()];
// 실제 출력도 문자열로 변환하여 배열 생성
const receivedOutput = consoleOutput.map((date) => new Date(date).toString());
// 예상 출력과 실제 출력을 비교하여 테스트 진행
expect(receivedOutput).toEqual(expectedOutput);
// 모의 타이머 복원
vi.useRealTimers();
});
내장객체의 경우엔 많이 써보면서 익힐 수 밖에 없다. 테스트 코드와 병행하니 배움의 폭이 하나를 배우더라도 몇 배로 배울 수 있게 된다. 테스트 코드에 `async/await` 가 많이 등장하는데, 빨리 속도를 따라 잡아서 완전한 이해를 하고 포스팅을 해보아야겠다.
Dream Coding Academy | 자바스크립트 마스터리 (ES6+)🎥
ChatGPT 🤖
'Test Code' 카테고리의 다른 글
`toBe`,`toEqual`과 `toStrictEqual`의 차이점 (0) | 2023.08.10 |
---|---|
What is Vitest? Vite와 함께 알아보자 + 코드 커버리지 확인 (0) | 2023.08.09 |
New 맥북에서 pnpm + Vite 환경 + Vitest 구축하기 (2) | 2023.08.05 |