[Jest] toBe vs toEqual vs toStrictEqual

이썸이·2024년 6월 12일
0

코테에서 주어진 조건의 예외 처리를 위해 Jest로 테스트코드 작성중인데, 기대 결과를 toBe() 로 넣고 테스트를 실행하고 있다.

문제 상황

| 프로그래머스 - 마지막 두 원소

풀이

function solution(num_list) {
  /**
   * 2 ≤ num_list의 길이 ≤ 10
   * 1 ≤ num_list의 원소 ≤ 9
   */

  assert(2 <= num_list.length && num_list.length <= 10, "Invaild array size");
  for (let i = 0; i < num_list.length; i++) {
    assert(1 <= num_list[i] && num_list[i] <= 9);
  }

  // length -1 > length-2 이면
  // (length -1) - (length-2) 추가
  const lastIndex = num_list.length - 1;
  if (num_list[lastIndex] > num_list[lastIndex - 1]) {
    num_list.push(num_list[lastIndex] - num_list[lastIndex - 1]);
  } else {
    // 아니면 (length -1)*2 추가
    num_list.push(num_list[lastIndex] * 2);
  }

  return num_list;
}

테스트 코드


test("[5, 2, 1, 7, 5]", () => {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toBe([5, 2, 1, 7, 5, 10]);
});

테스트 결과

테스트를 실행해보니 아래와 같이 테스트가 제대로 돌지 않았다.

문제를 잘못 풀었나 싶어서 console에 num_list를 찍어보기도 했다.


function solution(num_list) {
  /**
   * 2 ≤ num_list의 길이 ≤ 10
   * 1 ≤ num_list의 원소 ≤ 9
   */

  assert(2 <= num_list.length && num_list.length <= 10, "Invaild array size");
  for (let i = 0; i < num_list.length; i++) {
    assert(1 <= num_list[i] && num_list[i] <= 9);
  }

  // length -1 > length-2 이면
  // (length -1) - (length-2) 추가
  const lastIndex = num_list.length - 1;
  if (num_list[lastIndex] > num_list[lastIndex - 1]) {
    num_list.push(num_list[lastIndex] - num_list[lastIndex - 1]);
  } else {
    // 아니면 (length -1)*2 추가
    num_list.push(num_list[lastIndex] * 2);
  }

  console.log(num_list); // <- 여기 추가
  return num_list;
}

console에 찍어봤을 땐 값이 제대로 들어간 거 같은데 뭐가 문제일까 싶어 toBe의 주석과 Received된 결과를 살펴보았다. → serializes to the same string

해결 방법

우선 받은 결과에 찍힌 문구가 무슨 의미인지 구글링해보았다.
| 참고 블로그
| Stack overflow

  • 참고한 블로그에 작성을 잘 해주셔서 하나씩 살펴보니 이해가 됐다.

toEqual의 존재를 깨달음

지금까지 사용한 toBe() 는 객체가 아닌 그 객체의 참조값(메모리 주소)을 비교하지만, toEqual() 은 객체 내부의 값을 비교한다.
그래서 테스트 코드를 수정하고 다시 테스트를 돌려봤다.

test("[5, 2, 1, 7, 5]", () => {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toEqual([5, 2, 1, 7, 5, 10]); // <- toBe -> toEqual
});


야호 성공이다!

그런데 더 쉬운 방법이 있었다


포스트를 작성하다 보니 친절하게 안내되어 있었다.

  • toStrictEqual 로 바꿔보세요.

네.

test("[5, 2, 1, 7, 5]", () => {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toStrictEqual([5, 2, 1, 7, 5, 10]); // toEqual -> toStrictEqual
});


야호!

그런데 이러면 toEqual과 toStrictEqual은 무슨 차이가 있는 거지?

toStrictEqual

| 공식 문서
toEqual보다 엄격한 equal
undefined를 고려한다.

먼저 toEqual을 테스트 해보자

// toEqual
test("toEqual의 undefined 구분 여부", () => {
  const obj = { a: undefined, b: 1 };

  function test(testObj) {
    return testObj;
  }

  expect(test(obj)).toEqual({ b: 1 });
});

// toStrictEqual
test("toStrictEqual의 undefined 구분 여부", () => {
  const obj = { a: undefined, b: 1 };

  function test(testObj) {
    return testObj;
  }

  expect(test(obj)).toStrictEqual({ b: 1 });
});


toEqual은 테스트가 통과됐지만(undefined가 할당된 a는 없는 값으로 친다), toStrictEqual은 undefined라는 값으로 할당된 값이 있는지를 확인하기 때문에 테스트에 걸렸다.

결론

객체 타입의 값을 비교할 때에는 toStrictEqual 을 사용하는 게 내가 의도한 값으로 정확히 비교된다.


조금의 생각

  • 정확히 내부가 어떻게 도는지는 모르겠지만.. const로 변수 선언 시 원시 타입은 수정할 수 없지만 객체 타입은 메모리 주소가 할당되기 때문에 이후 수정할 수 있는 메커니즘과 관련있을 거 같다는 생각이 든다.

0개의 댓글