본문 바로가기
TIL/TIL

(unit test) A note on testing object equality

by koreashowme 2020. 1. 15.

우리는 다음과 같이 두 배열, [1, 2, 3] === [1, 2, 3]을 비교할 수 없다는 것을 압니다. 각 배열에 해당하는 내용을 비교하는 것이 아니라 각 배열에 할당된 메모리 주소를 비교하기 때문입니다.

아래와 같은 방식으로, 간단한 값인 숫자와 문자열로만 이루어진 배열이라는 가정하에 두 배열을 비교해주는 함수를 작성할 수 있습니다

(예를 들어, object가 들어있거나 또 다른 배열이 들어있는 배열은 아니라는 말입니다).

이러한 간단한 값을 Primitive type은 scalar type 이라고 부른다는 것 기억하고 있지요?

 

function assertArraysEqual(actual, expected, testName) {

  var areEqualValues = actual.every(function(item, i) {

   return item === expected[i];

});

  var areEqualLength = (actual.length === expected.length);

  if (areEqualLength && areEqualValues) {

     console.log('passed');

} else {

console.log('FAILED [' + testName + '] Expected "' + expected + '", but got "' + actual + '"'); }

}

 

간단한 방법으로 배열 안에 값을 다 문자열로 만든 후 비교하는 방법이 있습니다.

JSON.stringify()와 같은 helper 함수를 사용하여 해결할 수 있습니다. JSON에 관해서는 JSON format 을 통해 더 자세히 살펴볼 수 있지만, 이 함수만 사용한다면 굳이 볼 필요는 없을 것입니다.

 

function assertObjectsEqual(actual, expected, testName) {

actual = JSON.stringify(actual);

expected = JSON.stringify(expected);

   if (actual === expected) {

      console.log('passed');

  } else {

      console.log('FAILED [' + testName + '] Expected ' + expected + ', but got ' + actual);

   }

}

그런데도 이 테스트 방식은 두 object를 비교하는 모든 경우의 수를 감지하기에 완벽한 테스트 방식은 아닙니다. object의 경우, key 값은 같을 수 있지만 순서가 다르게 될 수 있기 때문입니다. 키의 순서는 동일한지 여부를 파악할 때 비교의 대상이 되지 않아야 하지만 stringify() 을 하면 그 순서에 의해 둘이 다른 값으로 인지되기 때문입니다.

 

JSON.stringify({foo: 1, bar: 2}) //

"{"foo":1,"bar":2}" JSON.stringify({bar: 1, foo: 2}) //

"{"bar":1,"foo":2}"

 

이 말은즉슨, 완전한 "deep equality"를 확인하는 방법을 살펴보는 것은 이 코스에서 다루기에 너무 먼 이야기 입니다.

관심이 있으신 분들은 다음 사이트에 작성된 코드를 확인해보실 수 있습니다

 

기술 면접 중에 유닛 테스트를 할 때 여러분(당사자)만 "expected" 값에 대해 관리를 하게 됩니다. 그렇기 때문에, JSON.stringify를 사용하여 빠르게 비교를 한다고 하더라도 큰 문제가 되지 않을 것입니다. 단지, 인터뷰를 진행하는 사람에게 이러한 방법이 production 코드에서는 안전하지 않은 방법임에도 불구하고 왜 그렇게 작성하게 되었는지를 설명할 준비는 하셔야 할 것입니다.

 

comment