어제(12.22) 코드스쿼드 면접이 있었다.
코드스쿼드에 합격하기 위해 바닐라 자바스크립트를 제대로 공부하기 시작했고, 그만큼 간절했기 때문에 너무 떨렸다.
학원에 합격하는 것이 뭐가 그렇게 어렵냐고 할 수 있지만, 경쟁률도 높고 합격하지 못하면 1년 후에나 도전할 수 있기 때문에 정말 어렵다.
면접 질문을 예상해서 연습도 많이 했기에 어떤 질문이 나와도 다 대답할 수 있을 것이라 생각했다. 하지만 예상과는 다르게 면접이 아닌 테스트를 봤다.
테스트는 코드스쿼드를 알아볼 때 몇 번 봤었던 테스트 코드를 작성하는 것이었다.
하지만 테스트 코드를 직접 구현해 볼 생각은 한 번도 하지 않았었기 때문에 매우 당황스러웠고, 참고하라고 준 영상도 44분이라 다 보고 코드를 제출하는 데에는 한계가 있다고 생각했다.
그래서 영상을 잠깐 본 뒤에 구글링을 해서 테스트 코드에 대해 빠르게 학습했고, 그럴싸한 테스트 코드를 만들어 제출했다.
그 뒤 짧은 면접을 본 후 나는 합격했다.
합격의 기쁨에 어제는 TIL을 작성하지 못했다... 너무 기쁘다😁
테스트 코드가 뭘까?
테스트 코드는 내가 원하는 결과 값과 실제 출력된 결과 값이 일치하는지 확인하며 내가 작성한 코드가 원하는 대로 동작하는지 알아볼 수 있는 유용한 코드이다.
테스트 코드를 작성하게 되면 내 코드에 대한 확신을 가질 수 있고, 변경 사항이 있을 때에도 빠르게 확인해 볼 수 있다.
테스트 코드는 보통 Jest를 사용하는데, Jest를 사용하기 전에 직접 구현해보자.
우선 내가 구현해서 테스트가 필요한 함수를 가져오자.
// index.mjs
export const pushWordLeft = (word, count) => {
const splitedWord = word.split('');
const pushedWord = splitedWord.splice(0, count);
const result = [...splitedWord, ...pushedWord];
return result.join('');
};
난 코드스쿼드 미션을 볼 때 위 코드를 가지고 테스트를 해봤다.
함수는 간단하다. apple이라는 단어와 3이 들어가면 apple을 왼쪽으로 3만큼 밀어내고 밀린 단어는 반대 편에 붙게 된다.
즉, pushWordLeft('apple', 3) === 'leapp' 이 된다.
그렇다면 간단한 테스트 코드를 한 번 작성해보자.
// test.mjs
import {pushWordLeft} from './index.mjs';
const expect = (result) => {
return {
toBe: (expected) => {
if (result !== expected) {
throw new Error(`${result}와 ${expected}가 같지 않습니다.`);
}
},
};
};
expect(pushWordLeft('apple', 3)).toBe('leapp');
expect함수는 결과 값을 매개 변수로 가지며, 기대 값을 매개 변수로 가지는 toBe메소드를 반환한다.
이때, 결과 값과 기대 값이 다르면 error를 출력하는 간단한 함수이다.
즉, 위 코드를 실행하기 위해 터미널에
node test.mjs
를 입력해보면 아무런 에러가 발생하지 않는 것을 확인할 수 있다. 이는 기대 값과 결과 값이 같다는 의미이다.
하지만 expect함수를
expect(pushWordLeft('apple', 3)).toBe('apple');
이렇게 바꾸게 되면
Error: leapp와 apple가 같지 않습니다.
에러가 발생하는 것을 볼 수 있다.
내가 원하는 값이 출력되지 않았기 때문에 코드가 잘못된 것을 바로 알 수 있다.
하지만 이것으로는 부족하다.
만약, 테스트해야 할 함수가 여러 개라면 어떤 함수에서 어떤 문제가 발생했는지에 대한 정확한 정보가 필요하기 때문이다.
// test.mjs
import {pushWordLeft, pushWordRight} from './index.mjs';
const it = (title, testCallback) => {
try {
testCallback();
console.log(`✔ ${title}`);
} catch (error) {
console.log(`❌ ${title}`);
console.error(error);
}
};
const expect = (result) => {
return {
toBe: (expected) => {
if (result !== expected) {
throw new Error(`${result}와 ${expected}가 같지 않습니다.`);
}
},
};
};
it('왼쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordLeft('apple', 3)).toBe('apple');
});
it('오른쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordRight('apple', 3)).toBe('apple');
});
더 정확한 정보를 얻고 싶을 때, it함수를 만들어서 확인해볼 수 있다.
이때는 성공했을 경우에도 성공 메시지를 띄워줄 수 있을 뿐만 아니라 기존 expect함수만 존재할 때에는 첫 번째 error가 발생한 지점에서 멈추는 현상이 발생하는데, it함수를 사용하면 에러가 발생한 모든 함수를 알려준다.
즉, 위 코드의 실행 결과는 다음과 같다.
❌ 왼쪽으로 단어 count만큼 밀어내기
Error: leapp와 apple가 같지 않습니다.
❌ 오른쪽으로 단어 count만큼 밀어내기
Error: pleap와 apple가 같지 않습니다.
이렇게 테스트 코드에 대해서 간략하게 알아보았고, 정말 편한 Jest를 한 번 사용해보도록 하겠다.
공식 사이트는 jestjs를 참고하자.
npm i -D jest
jest를 다운받은 후에
// package.json
"scripts": {
"test": "jest"
},
위와 같이 설정해준다.
그 후에 터미널에서 npm run test를 입력하면 filename.test.js에 있는 테스트 코드를 실행해 결과를 알려준다. 단순히 test.js파일에 해도 상관 없다.
또한, node.js에서 실행되는 것이라서 그런지 export나 import를 지원하지 않고 require과 exports를 사용해야 하는 것 같다.
// index.js
exports.pushWordLeft = pushWordLeft;
exports.pushWordRight = pushWordRight;
// push.test.js
const {pushWordLeft, pushWordRight} = require('./index.js');
it('왼쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordLeft('apple', 3)).toBe('leapp');
});
it('오른쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordRight('apple', 3)).toBe('pleap');
});
위 코드가 끝이다.
우리가 지금까지 구현했던 it과 expect함수를 이미 Jest는 가지고 있다.
또한, 터미널을 확인해보면 성공하면 초록색, 실패하면 빨간색으로 표시되기 때문에 가독성이 뛰어나고, 어느 부분이 잘못되었는지도 알려준다.
실패했을 때의 에러 메시지를 살펴보자.
테스트를 통과하지 못한 함수의 title을 보여주고, 틀린 부분도 보여주고 있는 것을 확인할 수 있다.
가독성이 좋은 Jest를 꼭 사용하도록 하자.
마지막으로, describe를 알아보면,
describe('단어 밀어내기', () => {
it('왼쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordLeft('apple', 3)).toBe('leapp');
});
it('오른쪽으로 단어 count만큼 밀어내기', () => {
expect(pushWordRight('apple', 3)).toBe('pleap');
});
});
이와 같이 비슷한 테스트 케이스를 묶어 하나의 title로 분류할 수 있다.
지금까지 테스트 코드에 관해 알아보았고, 테스트 코드는 내가 작성한 코드를 점검하며 코드에 대한 확신을 가질 수 있게 되고, 유지보수를 쉽게 하며, 안정성을 높여 주기 때문에 꼭 사용해야겠다는 생각을 가지게 되었다.
항상 콘솔에 내가 원하는 값이 나왔는지 비교해가면서 함수를 만들어왔는데, 이제는 그럴 필요가 사라졌고, 더 정교하게 테스트를 해볼 수 있을 것 같다.
어제 미션을 받았을 때, 많이 당황했지만 오늘 테스트 코드에 대한 공부를 해보면서 왜 이런 미션을 주셨는지 알 수 있었다.
함수를 작성하고, 코드를 짜는 것보다 테스트가 더 중요하기 때문이 아닐까? 라는 생각을 했다.
이제부터는 테스트 코드를 적극적으로 사용할 것이다.