Różnica między assert.equal i assert.deepEqual w testowaniu Javascript z Mocha?

94

Używam Mocha do testowania małego modułu w mojej aplikacji Express.js. W tym module jedna z moich funkcji zwraca tablicę. Chcę sprawdzić, czy tablica jest poprawna dla danego wejścia. Robię to w ten sposób:

suite('getWords', function(){
    test("getWords should return list of numbers", function() {
        var result = ['555', '867', '5309'];
        assert.equal(result, getWords('555-867-5309'));
    });
});

Po uruchomieniu pojawia się następujący błąd potwierdzenia:

AssertionError: ["555","867","5309"] == ["555","867","5309"]

Jednak kiedy zmieniam mój test na an assert.deepEqual, test kończy się pomyślnie. Zastanawiałem się, czy to przypadek ==vs ===, ale jeśli wejdę

[1,2,3] === [1,2,3]

do wiersza poleceń node.js, nadal otrzymuję fałsz.

Dlaczego tablice nie porównują tak, jak inne wartości (np. 1 == 1)? i jaka jest różnica między assert.equal i assert.deepEqual?

mshell_lauren
źródło

Odpowiedzi:

161

Dlaczego tablice nie porównują tak, jak robią to inne wartości (np. 1 == 1)

Liczby, ciągi znaków, wartości logiczne nulli undefinedsą wartościami i są porównywane zgodnie z oczekiwaniami. 1 == 1, 'a' == 'a'i tak dalej. Różnica między wartościami ===iw ==przypadku wartości polega na tym ==, że najpierw spróbuje wykonać konwersję typów, dlatego, '1' == 1ale nie '1' === 1 .

Z drugiej strony tablice są obiektami. ===iw ==tym przypadku nie oznaczają, że operandy są semantycznie równe, ale odnoszą się do tego samego obiektu .

Jaka jest różnica między assert.equal i assert.deepEqual?

assert.equalzachowuje się jak wyjaśniono powyżej. W rzeczywistości zawodzi, jeśli argumenty są !=, jak widać w źródle . Dlatego nie powiedzie się to w przypadku tablic ciągów liczbowych, ponieważ chociaż są one zasadniczo równoważne, nie są tym samym obiektem.

Z drugiej strony, głęboka (aka strukturalna) równość nie sprawdza, czy operandy są tym samym obiektem, ale raczej, że są równoważne. W pewnym sensie można powiedzieć, że wymusza porównywanie obiektów tak, jakby były wartościami.

var a = [1,2,3]  
var b = a              // As a and b both refer to the same object
a == b                 // this is true
a === b                // and this is also true

a = [1,2,3]            // here a and b have equivalent contents, but do not
b = [1,2,3]            // refer to the same Array object.
a == b                 // Thus this is false.

assert.deepEqual(a, b) // However this passes, as while a and b are not the 
                       // same object, they are still arrays containing 1, 2, 3

assert.deepEqual(1, 1) // Also passes when given equal values

var X = function() {}
a = new X
b = new X
a == b                 // false, not the same object
assert.deepEqual(a, b) // pass, both are unadorned X objects
b.foo = 'bar'
assert.deepEqual(a, b) // fail!
numery1311407
źródło
4
Świetne wyjaśnienie deepEqual(); nie jest to coś, o czym myślisz w porównaniu, dopóki nie natrafisz na to.
brandonscript