📝

Mocha を使うときは assert.strictEqual を使ったほうがいいな?という話

2021/07/04に公開

こんにちは、@armorik83 です。タイムリーな話題で、ついさっきの@Jxck_さんのつぶやきが気になったので調べてみました。

<blockquote class="twitter-tweet" lang="en"><p lang="ja" dir="ltr">あれ?久しぶりに power-assert じゃない普通の assert 使ったら、表示が改善してる。こんなにわかりやすかったっけ?</p>— Jxck (@Jxck_) <a href="https://twitter.com/Jxck_/status/597987303387111424">May 12, 2015</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

Mocha 2.2.3 から賢くなっていた

どうもこれを見るに、reporter/baseという箇所に手が入ったようで、これによってassertの出力が賢くなっていました。

比較してみよう

ソース

spec.js
var assert = require('assert');

it('test1 strictEqual', function() {
  var a = 'abcde';
  var b = 'abcdf';
  assert.strictEqual(a, b);
});

it('test1 eqeqeq', function() {
  var a = 'abcde';
  var b = 'abcdf';
  assert(a === b);
});

it('test2', function() {
  var a = {
    hoge: 12
  };
  var b = {
    hoge: 13,
    fuga: 56
  };
  assert.deepEqual(a, b);
});

assert + Mocha 2.2.1

npm i mocha@2.2.1 && $(npm bin)/mocha spec.js
  1) test1 strictEqual
  2) test1 eqeqeq
  3) test2

  0 passing (15ms)
  3 failing

  1)  test1 strictEqual:
     AssertionError: 'abcde' === 'abcdf'
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec.js:6:10)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

  2)  test1 eqeqeq:
     AssertionError: false == true
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec.js:12:3)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

  3)  test2:
     AssertionError: { hoge: 12 } deepEqual { hoge: 13, fuga: 56 }
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec.js:23:10)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

よく見る感じのやつです。なお、2.2.2 は欠番です。

assert + Mocha 2.2.3

npm i mocha@2.2.3 && $(npm bin)/mocha spec.js
  1) test1 strictEqual
  2) test1 eqeqeq
  3) test2

  0 passing (19ms)
  3 failing

  1)  test1 strictEqual:

      AssertionError: 'abcde' === 'abcdf'
      + expected - actual

      +"abcdf"
      -"abcde"

      at Context.<anonymous> (spec.js:6:10)

  2)  test1 eqeqeq:

      AssertionError: false == true
      + expected - actual

      +true
      -false

      at Context.<anonymous> (spec.js:12:3)

  3)  test2:

      AssertionError: { hoge: 12 } deepEqual { hoge: 13, fuga: 56 }
      + expected - actual

       {
      +  "fuga": 56
      +  "hoge": 13
      -  "hoge": 12
       }

      at Context.<anonymous> (spec.js:23:10)

おおおっ!? assert(a === b)よりassert.strictEqual(a, b)の方が情報量が多いことが分かります。個人的にはタイプ量の好みでassert()を使っていたんですが、Mocha と標準 assert の組み合わせではstrictEqual()がよさ気なことに気付けました。

power-assert + Mocha 2.2.3

power-assertとも比較しておきます。1 行目のみ書き換えます。

spec.js
var assert = require('power-assert');
npm i power-assert espower-cli mocha@2.2.3
$(npm bin)/espower spec.js > spec-esp.js && $(npm bin)/mocha spec-esp.js
  1) test1 strictEqual
  2) test1 eqeqeq
  3) test2

  0 passing (49ms)
  3 failing

  1)  test1 strictEqual:

      AssertionError:   # spec.js:6

  assert.strictEqual(a, b)
                     |  |
                     |  "abcdf"
                     "abcde"

      + expected - actual

      +"abcdf"
      -"abcde"

      at Context.<anonymous> (spec-esp.js:5:12)

  2)  test1 eqeqeq:

      AssertionError:   # spec.js:12

  assert(a === b)
         | |   |
         | |   "abcdf"
         | false
         "abcde"

  --- [string] b
  +++ [string] a
  @@ -1,5 +1,5 @@
   abcd
  -f
  +e


      + expected - actual

      +true
      -false

      at Context.<anonymous> (spec-esp.js:18:5)

  3)  test2:

      AssertionError:   # spec.js:23

  assert.deepEqual(a, b)
                   |  |
                   |  Object{hoge:13,fuga:56}
                   Object{hoge:12}

      + expected - actual

       {
      +  "fuga": 56
      +  "hoge": 13
      -  "hoge": 12
       }

      at Context.<anonymous> (spec-esp.js:30:12)

power-assert では、assert(a === b)使用時の情報量の方が豊富ですので、何を使うかはテスト対象や好みによります。標準の assert ログが強力になるのは嬉しい事ですね!

補足 Chai + Mocha 2.2.1

@t_wada さんからChai等の Assertion ユーティリティについて補足を頂きました。Chai は使ったことがないので、この際検証してみます。

var chai = require('chai');
var expect = chai.expect;
var assert = chai.assert;

it('test1 chai should', function() {
  chai.should();
  var a = 'abcde';
  var b = 'abcdf';
  a.should.be.a(a, b);
});

it('test1 chai expect', function() {
  var a = 'abcde';
  var b = 'abcdf';
  expect(a).to.equal(b);
});

it('test1 chai assert', function() {
  var a = 'abcde';
  var b = 'abcdf';
  assert.equal(a, b);
});

it('test2', function() {
  var a = {
    hoge: 12
  };
  var b = {
    hoge: 13,
    fuga: 56
  };
  assert.deepEqual(a, b);
});
npm i chai mocha@2.2.1 && $(npm bin)/mocha spec-chai.js
  1) test1 chai should
  2) test1 chai expect
  3) test1 chai assert
  4) test2

  0 passing (17ms)
  4 failing

  1)  test1 chai should:
     AssertionError: abcdf: expected 'abcde' to be an abcde
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec-chai.js:9:15)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

  2)  test1 chai expect:

      AssertionError: expected 'abcde' to equal 'abcdf'
      + expected - actual

      +abcdf
      -abcde

      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec-chai.js:15:16)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

  3)  test1 chai assert:
     AssertionError: expected 'abcde' to equal 'abcdf'
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec-chai.js:21:10)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

  4)  test2:

      AssertionError: expected { hoge: 12 } to deeply equal { hoge: 13, fuga: 56 }
      + expected - actual

       {
      +  "fuga": 56
      +  "hoge": 13
      -  "hoge": 12
       }

      at Function.assert.deepEqual (/Users/armorik83/Desktop/mochasandbox/node_modules/chai/lib/chai/interface/assert.js:205:32)
      at Context.<anonymous> (/Users/armorik83/Desktop/mochasandbox/spec-chai.js:32:10)
      at callFn (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:266:21)
      at Test.Runnable.run (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runnable.js:259:7)
      at Runner.runTest (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:387:10)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:470:12
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:312:14)
      at /Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:322:7
      at next (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:257:23)
      at Immediate._onImmediate (/Users/armorik83/Desktop/mochasandbox/node_modules/mocha/lib/runner.js:289:5)
      at processImmediate [as _immediateCallback] (timers.js:357:17)

Stack trace が長いものの、Mocha 2.2.1 時点で優秀ですね! 知りませんでした。

補足 Chai + Mocha 2.2.3

npm i chai mocha@2.2.3 && $(npm bin)/mocha spec-chai.js
  1) test1 chai should
  2) test1 chai expect
  3) test1 chai assert
  4) test2

  0 passing (24ms)
  4 failing

  1)  test1 chai should:
     AssertionError: abcdf: expected 'abcde' to be an abcde
      at Context.<anonymous> (spec-chai.js:9:15)

  2)  test1 chai expect:

      AssertionError: expected 'abcde' to equal 'abcdf'
      + expected - actual

      +"abcdf"
      -"abcde"

      at Context.<anonymous> (spec-chai.js:15:16)

  3)  test1 chai assert:
     AssertionError: expected 'abcde' to equal 'abcdf'
      at Context.<anonymous> (spec-chai.js:21:10)

  4)  test2:

      AssertionError: expected { hoge: 12 } to deeply equal { hoge: 13, fuga: 56 }
      + expected - actual

       {
      +  "fuga": 56
      +  "hoge": 13
      -  "hoge": 12
       }

      at Context.<anonymous> (spec-chai.js:32:10)

なるほど、Chai を使うならexpect(a).to.equal(b)が一番情報量が豊富な結果となりました。かつて使い慣れたテストフレームワークがあったり、タイプ量、読みやすさ等、好みかと思います。

Chai 以外は割愛します。


期せずして Assertion ユーティリティの比較記事となりました。色々ありますね! タイトルは若干モニョってますが、もう最初のままで。

以上です。

Discussion