Jest를 사용한 TDD 연습 - 기본 Matcher

맨날·2021년 6월 5일
0

Jest를 사용한 TDD

목록 보기
2/2

Jest는 matcher를 사용하여 사용자가 원하는 값을 테스트 하도록 도와줍니다.

Common Matchers

toBe

toBe는 값이 정확히 일치하는지 여부를 확인해줍니다.

test('tow plus tow is four', () => {
  expect(2 + 2).toBe(4);
})

toBe를 사용할때 주의해야 할 점은 객체를 테스트할 때입니다. toBe를 통한 객체 테스트는 값의 일치가 아니라, 두개의 값 모두 같은 경우에 통과합니다(Object.is).

test('object', () => {
  const data = { one: 1 };
  const result = data;
  
  expect(data).toBe(result); // pass
  expect(data).toBe({ one: 1 }); // fail
});

toEqual

객체 또는 배열의 값을 비교하여 일치하는지 여부를 판단합니다.

test('object assingment', () => {
  const data = { one: 1 };
  
  expect(data).toEqual({ one: 1 }); // pass
});

not

현재 사용하고 있는 matcher의 반대의 matcher를 사용하고 싶을 때는 not을 사용합니다.

test('adding positive number is not zero', () => {
  for (let = 1; a < 10; a++) {
    for (let b = 1; b < 10; b++) {
      expect(a + b).not.toBe(0);
    }
  }
});

Truthiness

테스트시에 undefined, null, false 값에 대한 구별하여야 하지만, 이들을 다르게 처리하고 싶지 않을 수도 있습니다. Jest에서는 이에 대한 matcher를 준비해 놓았습니다.

test('null', () => {
  const n = null;
  expect(n).toBeNull();
  expect(n).toBeDefined();
  expect(n).not.toBeUndefined();
  expect(n).not.toBeTruthy();
  expect(n).toBeFalsy();
});

test('zero', () => {
  const z = 0;
  expect(z).not.toBeNull();
  expect(z).toBeDefined();
  expect(z).not.toBeUndefined();
  expect(z).not.toBeTruthy();
  expect(z).toBeFalsy();
});

Numbers

숫자를 비교하는 방법과 관련된 matcher 또한 존재합니다.

test('two plus two', () => {
  const value = 2 + 2;
  expect(value).toBeGreaterThan(3);
  expect(value).toBeGreaterThanOrEqual(3.5);
  expect(value).toBeLessThan(5);
  expect(value).toBeLessThanOrEqual(4.5);

  // 숫자 테스트에서는 toBe와 toEqual은 동일합니다.
  expect(value).toBe(4);
  expect(value).toEqual(4);
});

부동 소수점 테스트에서는 toBe가 아닌 toBeCloseTo를 사용하여야 합니다.

test('adding floating point numbers', () => {
  const value = 0.1 + 0.2;
  
  expect(value).toBe(0.3); // fail
  expect(value).toBeCloseTo(0.3); // pass
});

String

문자열 테스트를 할때 정규식으로 테스트하기 위한 matcher가 준비되어 있습니다.

test('there is no I in team', () => {
  expect('team').not.toMatch(/I/);
});

test('but there is a "stop" in Christoph', () => {
  expect('Christoph').toMatch(/stop/);
});

문자열 테스트에서 toBetoEqual도 사용가능합니다.

Arrays and iterables

배열 또는 iterable에서 일부 아이템이 존재하는지 여부를 toContain 테스트 할 수 있습니다.

const shoppingList = [
  'diapers',
  'kleenex',
  'trash bags',
  'paper towels',
  'milk',
];

test('the shopping list has milk on it', () => {
  expect(shoppingList).toContain('milk');
  expect(new Set(shoppingList)).toContain('milk');
})

Exceptions

함수를 호출 했을 때 에러가 발생하는 경우에 대한 테스트도 진행할 수 있습니다. toThrow를 사용하면 됩니다.

function compileAndroidCode() {
  throw new Error('you are using the wrong JDK');
}

test('compiling android goes as expected', () => {
  expect(() => compileAndroidCode()).toThrow(); // 에러 발생 여부 확인
  expect(() => compileAndroidCode()).toThrow(Error); // 특정 에러 발생 여부 확인
  
  expect(() => compileAndroidCode()).toThrow('you are using the wrong JDK'); // 에러 메시지 확인
  expect(() => compileAndroidCode()).toThrow(/JDK/) // 에러 메시지를 정규식으로 확인
})

Object

toMatchObject

객체가 가진 일부 속성 또는 속성에 해당 하는 값을 가지고 있는지 여부를 테스트 하고 싶을 수도 있습니다.

const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove'],
    area: 20
  }
};
const desiredHouse = {
  bath: true,
  kitchen: {
    amenities: ['oven', 'stove'],
    area: expect.any(Number),
  },
}

test('the house has my desired features', () => {
  expect(houseForSale).toMatchObject(desiredHouse);
});

위의 코드에서 확인해 볼 수 있듯이, 객체가 가진 일부 속성에 대해서 테스트할 수 있습니다. expect.any(classType)을 통해서 값이 아닌 속성의 타입을 테스트할 수도 있습니다.

이때 배열을 테스트할 때는, 모든 요소를 가지고 있어야 합니다. 배열의 일부 요소만 포함되어 있음을 테스트할 때는 expect.arrayContaining를 사용하면 됩니다.

test('arrayContaining', () => {
  expect(['oven', 'stove']).toMatchObject(['oven', 'stove']); // pass
  expect(['oven', 'stove']).toMatchObject(['oven']); // fail
  expect(['oven', 'stove']).toMatchObject(expect.arrayContaining(['oven'])); // pass
});

objectContaining

objectContainingtoMatchObject와 유사한 기능을 가지고 있습니다. 아래와 같이 사용하면 테스트에서 통과하는 것을 확인할 수 있습니다.

test('objectContaining', () => {
  const data = { position: { x: 0, y: 0 }, a: 1 };
  
  expect(data).toMatchObject({ a: 1 }); // pass
  expect(data).toEqual(expect.objectContaining({ a: 1 })); // pass
});

그럼 두개의 차이점을 알아보도록 하겠습니다. toMatchObject는 값을 비교할 때 하위 객체의 요소까지 일부 속성을 가지고 있는지 테스트해 줍니다. 하지만 objectContaining는 하위 객체는 완전한 속성을 가지고 있어야 테스트에 통과합니다.

test('objectContaining', () => {
  const data = { position: { x: 0, y: 0 }, a: 1 };
  
  expect(data).toMatchObject({ position: { x: 0 } }); // pass
  expect(data).toEqual(expect.objectContaining({ position: { x: 0 } })); // fail
  expect(data).toEqual(expect.objectContaining({ position: expect.objectContaining({ x: 0 }) }))
});

0개의 댓글