Jest 문서보기

이진희·2022년 4월 2일
0

Introduction

  • jest는 babel, webpack, ts와 함께 사용가능하고 CLI환경에서도 원하는 옵션, 원하는 config파일을 지정해 테스트를 실행할 수 있다.(npm, yarn 모두 지원)

Using Matchers 매쳐가 뭐여

: Jest는 당신이 다른 방법들로 값들을 테스트하기 위해 “Matcher”를 사용

  • 주로 사용되는 matchers를 볼거고, 자세한건 expect API DOCS 참조

Common Matchers

test(’test 내용’ , ()⇒{expect(”실행내용").toBe(기대 결과값)})

expect ⇒ “expectation” object를 반환함. 이 오브젝트로는 matcher를 부르는 것 제외하고는 크게 다른 일을 하는 일은 잘 없을 것임.

여기서는 toBe matcher가 사용됨. (toBe는 기댓값과 결과가 완전히 일치하는지 파악하기 위해 Object.is method를 사용한다), 만약 object의 내용이 같은지 체크하려면(그러니까 가리키는 객체가 동일한 것이 아닌, 객체 안에 담겨있는 값이 같은지) toBe matcher가 아닌 toEqueal 매쳐를 사용해햐 한다.

matcher를 붙히기 전 expectationObject.not.[matcher] 처럼 not메소드 뒤에 매쳐를 체이닝해서 실행 시키면, matcher로 넣은 것을 만족하지 않는지도 테스트 가능.

Truthiness

undefined : 아예 정의가 되어 있지 않은 것, null : 빈 것, false:boolean값

일반 js에서 이 세가지는 크게 다르지 않게 사용될 수 있지만, Jest에서는 세개를 구분지어줘야 할 때가 있다.

하지만 구분하기 싫을 때는, Jest는 당신이 원하는 것을 명확하게 해줄 수 있는 헬퍼를 제공한다.(즉, 구분짓는 걸 해주는 ‘헬퍼'라는 게 있다는 거쥬)

  • toBeNull : matches only null
  • toBeUndefined : matches only undefined ↔ toBeDefined
  • toBeTruthy : if 스테이트가 ‘true’라고 판단하는 모든 것(0이 아닌 모든 수, 비지 않은 배열, true...)
  • toBeFalsy : if 스테이트가 ‘false’라고 판단하는 모든 것(0, 빈 배열, false, undefine, null...)

정확하게 니가 원하는대로 테스팅할 수 있게 뭐써야할지 판단해야겠지

Numbers

숫자 비교해주는 matcher

  • .toBeGreaterThan(number);
  • .toBeGreaterThanOrEqual(number);
  • .toBeLessThan(number);
  • .toBeLessThanOrEqual(number);
  • number에 한해 .toBe(number) === .toEqual(number) 객체에는 다르게 적용되는거 알쥬?
  • .toBeCloseTo(floatingNumber) :소수자리수 비교. 소수자리는 사실상 미세한 오차범위가 있을 수 밖에 없기에 내가 지정한 값과 가까운가로 판단.

Strings

.toMatch(regularExpression) ⇒ regularExpression에 맞아떨어지는지 평가

.not.toMatch(regularExpression) ⇒ 정규표현식에 해당되지 않는지 평가

Arrays and Iterables

.toContain(element) : array, set, object같은데서 element를 갖고 있는지 판단

예외

오류상항/예외상황 발생시를 테스트하고 싶을 때 toThrow() Matcher사용

그 외의 더 상세한 내용들.

reference docs

비동기코드 테스팅

js에서 비동기는 굉~장히 흔함(싱글쓰레드 언어임). Jest는 다른 코드를 테스트하러가기 전에 테스트가 완료된 코드인지를 알아야 함. 이 테스트가 끝났을 때를 알려주는 방법이 있음.

Callbacks

가장 흔한 비동기패턴

JEST는 콜백함수를 실행하는 걸 기다리지 않고, 제일 먼저 실행된 함수의 코드를 끝까지 실행시켰다면 테스트를 완료시킬 것임 ⇒ 근데 내 콜백함수는 아직 진행중이므로 테스트가 불가능함.

  • ⇒ done을 이욯하자. Jest는 done콜백이 불릴때까지 테스트를 마치지 않을 것임.
  • 만약 done함수가 계속 불리지 않는다면, 테스트는 실패할것임.
  • done()은 Promisesd와 같이 쓰면 안댐. 섞어 쓰면 메모리 누수 발생할 수 있음.
wrong code

test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter');
		//JEST DOESNT WAIT!
  }

  fetchData(callback);
});
right code
test('the data is peanut butter', done => {
  function callback(data) {
    try {
      expect(data).toBe('peanut butter');
      done(); <= JEST WAIT THIS
    } catch (error) {
      done(error);<= JEST WAIT THIS
    }
  }

  fetchData(callback);
});

Promises

  • 프로미스 사용하면 더 직관적인 비동기테스트 방식 사용 가능
  • 테스트에서 Promise 객체를 반환하면, Jests는 resolve되기를 기다리고, reject되었다면 자동적으로 테스트가 실패
test('the data is peanut butter', () => {
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  });
});
Be sure to return the promise - if you omit this return statement, your test will complete before the promise returned from fetchData resolves and then() has a chance to execute the callback.

If you expect a promise to be rejected, use the .catch method. Make sure to add expect.assertions to verify that a certain number of assertions are called. Otherwise, a fulfilled promise would not fail the test.

test('the fetch fails with an error', () => {
  expect.assertions(1);
  return fetchData().catch(e => expect(e).toMatch('error'));
});

.resolves/.rejects

그냥 return expect(asyncFunction()).resolves.toBe(’비교값’)

    return expect(asyncFunction()).rejects.toMatch(’error’);

Async/Await

test 두번째에 콜백함수를 넣어줄때 async함수로 지정.

const data = await fetchData();

expect(data).toBe(’비교값') 이렇게 간단히도 가능

에러는 try{}catch(e){expect(e).toMatch(’error’)}로 간단히 해결

Setup and Teardown

테스트 실행 전/실행 후에 따로 실행해야하는 작업들이 있을 것이다. 그 작업들이 테스트를 할 때마다 실행해야 하는 작업일 경우, 이런 작업들을 도와주는 헬퍼가 있다.

Repeating Setup For Many Tests

  • 테스트 실행 전/실행 후에 반복적으로 진행해야 하는 작업이 있다면 beforeEach(), afterEach()를 사용할 수 있다.
  • beforeEach와 afterEach에서도 Jest에서 비동기를 다루는 방법을 그대로 사용하면 된다.(done()콜백 함수 실행 or Promise객체 반환)
beforeEach(()=>{테스트전에 실행해야 하는 일});

afterEach(()=>{테스트 후에 실행해야 하는 일});
그냥 이케이케 덜렁 적어주면됨 약간 useEffect같은 느낌으로다가

One-Time Setup

  • beforeEach와 다르게 딱!한번만! 실행하면 되는 경우 beforeAll과 afterAll을 사용
  • 한 번 불러와서 해당 데이터를 계속 재활용하는 경우에 사용!

Scoping(describe)

기본적으로 beforeAll과 afterAll은 파일 내에 있는 모든 테스트에 적용된다.

그런데 만약 테스트 일부에만 적용하고 싶다면? ⇒describe block안에서 작성해 scoping을 할 수 있다.

describe('matching cities to foods', () => {
  // Applies only to tests in this describe block
  beforeEach(() => {
    return initializeFoodDatabase();
  });

  test('Vienna <3 veal', () => {
    expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
  });

  test('San Juan <3 plantains', () => {
    expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
  });
});
//이케 describe 내에서 beforeEach/afterEach/beforeAll/afterAll 을 적용하면 해당 describe안에 있는 테스트에만 적용된다. 같은 파일 내에 있더라도 해당 스코프의 밖에 있다면 적용되지 않는다.
  • describe block밖에도 beforeEach/beforeAll이 있다면 그게 먼저 실행되고 describe 내의 beforeEach/beforeAll이 실행되므로 유의할 것!

Order of execution of describe and test blocks

테스트 순서 정하기~

  • Jest는 test보다 모든 describe handler를 실행시킨다.
  • 이게 describe보다는 before/after안에서 셋업이 진행되어야 하는 이유다.
  • describe가 완료되면, 제스트는 자기들이 마주친 순서대로 테스트케이스를 실행시킨다.

General Advice

만약 테스트가 실패한다면 가장 먼저 테스트 하나만 실행해도 테스트가 실패하는지를 체크하는 것이다.

하나의 테스트만 따로 실행해보기 위해서는 test 명령어를 test.only로 변경해주면 된다.

만약 큰 덩어리의 일부로써 테스트를 할때는 실패하는일이 많은데, 해당 테스트 하나만 돌렸을 때 문제가 없다면 ‘이전 공유 상태'를 지우면 해결할 수 있다. 로그 데이터를 통해 beforeEach

어째뜬 공유 데이터를 확인해라! 이말이야, 이것때매 계속 fail하는 걸 수도 있으니꼐

Mock Function

  • mock : 모의

mock function은 실제 실행되는 함수를 지우고, 펑션이 호출되는 것을 캡쳐링하고, 생성자함수로 만들어진 객체를 캡쳐링하고, 리턴밸류의 테스트시간 설정을 허가함으로써 코드 간의 link를 테스트를 할 수 있게 해줌.

2가지 mock function이 있음 :

  1. 테스트 코드 내에서 사용할 mock function을 만드는 것.
  2. 모듈 의존성을 override하기 위해 manual mock을 작성하는 것.

Using a mock function

  • function forEach를 테스트 할 것임.
  • mock function을 이용해 mock의 스테이트를 검사할 수 있는데, 이는 콜백함수가 기대한대로 실행됐음을 확신함을 위함이다.

ex.

function forEach(items, callback) {
  for (let index = 0; index < items.length; index++) {
    callback(items[index]);
  }
}

const mockCallback = jest.fn(x => 42 + x);
forEach([0, 1], mockCallback);

// The mock function is called twice
expect(mockCallback.mock.calls.length).toBe(2);

// The first argument of the first call to the function was 0
expect(mockCallback.mock.calls[0][0]).toBe(0);

// The first argument of the second call to the function was 1
expect(mockCallback.mock.calls[1][0]).toBe(1);

// The return value of the first call to the function was 42
expect(mockCallback.mock.results[0].value).toBe(42);

.mock property

  • 모든 mock function은 .mock 프로퍼티를 갖는다.
  • .mock 프로퍼티는 함수가 어떻게 실행됐는지에 대한 데이터와 함수가 어떤것을 리턴하는지에 대한 데이터가 저장되는 장소다.
  • .mock 프로퍼티는 각 호출에 대한 this의 값을 따른다.

!!! js의 this와 프로토타입, bind, call, apply를 알아야할것같음!!!

mock return values ⇒이 부분은 잘모르겟음..!

  • mock function은 테스트 값을 주입하기 위해 사용할 수도 있다.
const filterTestFn = jest.fn();

// Make the mock return `true` for the first call,
// and `false` for the second call
filterTestFn.mockReturnValueOnce(true).mockReturnValueOnce(false);

const result = [11, 12].filter(num => filterTestFn(num));

console.log(result);
// > [11]
console.log(filterTestFn.mock.calls[0][0]); // 11
console.log(filterTestFn.mock.calls[1][0]); // 12

mock function점 알아보고

test example

commonJS 모듈 사용한 거임

sum.js

function sum(a, b) {
  return a + b;
}

function sumOf(numbers) {
  let result = 0;
  numbers.forEach((n) => {
    result += n;
  });
  return result;
}

//module.exports = sum;
exports.sum = sum;
exports.sumOf = sumOf;

sum.test.js

const { sum, sumOf } = require("./sum.js");
require("jest");

describe("sum", () => {
  it("1+2=3", () => {
    expect(sum(1, 2)).toBe(3);
  });

  it("calculates all numbers", () => {
    const array = [1, 2, 3, 4, 5];
    expect(sumOf(array)).toBe(15);
  });
});

package.json 에 테스트 스크립트 추가.

profile
슬로우 스타터

0개의 댓글