node.jsのソースを単体テストするmocha+chaiの使い方

node.jsのソースを単体テストするmocha+chaiの使い方

node.jsのソースを単体テストするmocha+chaiの使い方についてです。

ここでは、mocha4.0.0、chai4.1.2を使用しています。

まずchaiをrequireして、assertというchaiのAPIを使用します。

const chai = require('chai');
const assert = chai.assert;

次にテストしたいコードを書きます。

const chai = require('chai');
const assert = chai.assert;
const myFunc = function(a, b){
  return a+b;
};

テストは、mochaが用意してくれているdescribeメソッドを使用します。

以下、簡単な記述例です。

const chai = require('chai');
const assert = chai.assert;
const myFunc = function(a, b){
  return a + b;
};
describe('テストのタイトル', function () {
  it('myFuncのテスト', function() {
    assert.strictEqual(myFunc(1, 2), 3);
  });
});

describeの第一引数は、テストタイトルです。第二引数がcallback関数となっており、その中に、itメソッドを記述します。このitメソッド単位にテストを実行します。

その為、describeの中にはitメソッドはいくつでも記述することができます。

assert.strictEqualメソッドの第一引数と第二引数を比較します。

上記のファイルを「index.test.js」として保存します。

コマンドプロンプトから以下のように実行します。

C:\>mocha index.test.js // グローバルインストールの場合

結果は以下のようにOKなら緑色になります。NGなら赤色になります。

node.jsのソースを単体テストするmocha+chaiの使い方

describe.skip

describe.skip~とすることで、その中のitテストは全てスキップされます。

xdescribeと書いても同じです。

itだけをスキップしたいときは、it.skipもしくはxitと書きます。

describe.only

describe.only~とすることで、その中のitテストだけをテストすることができます。

it.only~とすることもできます。

これはよく使いますが、最後はonlyを削除するのを忘れないように注意してください。

describeの入れ子

describeの中にdescribeを書くことができます。

describe('タイトル', () => {
  describe('タイトル', () => {
    // ここにitを書く
  });
});</pre.

beforeEach

mochaにはbeforeEachと言うメソッドが用意されています。 beforeEachはdescribeの中、かつ、itの上に書きます。 各itテストの前でbeforeEachが実行されます。使い方の例としては、テストデータをインサートしたりとかでしょうか。 以下、記述例です。

beforeEach(function(done) {
  // ここに書く
  done();
});

afterEach

これはbeforeEachとは逆に、各itの終わりに実行されます。

エラー

ResourceInUseException: Table already exists: テーブル名

…そのテーブルが既に存在する場合にcreateTableすると発生する。

Promiseオブジェクトを比較する方法

Promiseオブジェクトをアサーションするのは少し難しいです。

が、chai-as-promisedモジュールを使えば簡単に比較することができるようになります。

インストールは以下のとおりです。

npm install chai-as-promised --save-dev

7.1.1をインストールしました。まず、chai-as-promisedを使わずに、以下のようなテストを実行してみます。

it('Promiseのテスト', function(){
  let p1 = Promise.resolve(123);
  expect(p1).to.deep.equal(123);
});

結果は以下のようにエラーとなります。

AssertionError: expected {} to deeply equal 123

次にchai-as-promisedを使ってみます。

chai.useを使用します。

const chai = require('chai');
const cap = require('chai-as-promised');
const expect = chai.expect;
chai.use(cap);// これが必要
describe('Promiseテスト', function () {
  it('Promiseのテスト1', function(){
    let p1 = Promise.resolve(123);
    expect(p1).to.deep.eventually.equal(123);
  });
});

expectの引数にPromiseオブジェクトを指定し、to.deep.equalではなく、to.deep.eventually.equalを使用します。

引数にはプロミスオブジェクトの結果を指定します。上記では、123になります。

このテストを実行すると結果は以下のように成功します。

C:\Users\xxx\Documents\vscode\apps>mocha index.js

 

Promiseテスト
√ Promiseのテスト1

 

1 passing (23ms)

参考サイト

chaiのエラー出力情報を無制限にする

chaiでエラーがでたとき{Objects}、、、というように簡素化されて表示されるのでObjectのどこが一致していないのか判断しづらいです。これを無制限に出力するには以下を記述することでObjectの中身を出力してくれるようになります。

chai.config.truncateThreshold = 0;

テストする

期待値と実際値を比較しますが、方法は無数にあります。

chai.expect(expected).to.be.null;// expectedがnullならpass
chai.expect(actual).to.equals(expected);// expectedとactualが等しいならpass
chai.expect(actual).to.equal(expected);// expectedとactualが等しいならpass
chai.expect(actual).to.not.equal(expected);// expectedとactualが等しくないならpass
chai.expect(actual).to.be.an('array');// actualが配列ならpass
chai.expect(actual).to.be.greaterThan(expected);// actual > expectedならpass (数値)
chai.expect({ojb:3}).to.deep.equal({ojb:3});// 比較する値がオブジェクトのばあいはあの場合はto.deep.equalで比較する
chai.expect(stub.callCount).to.equal(1);// sinon.stubメソッドが実行された回数を比較
chai.expect({'Message':'aiueo'}).to.have.property('Message');// プロパティにMessageが存在する場合pass
chai.expect('111').to.have.lengthOf(3);// 文字列長が3であるかどうかを比較
chai.assert.operator(-1, '<', 3);
chai.assert.closeTo(2.5,3,0.5);
chai.assert.deepEqual({},{});// 第一引数のオブジェクトと第二引数のオブジェクトを比較し、同じならpass
chai.assert.notDeepEqual({},{'a':true});// 第一引数のオブジェクトと第二引数のオブジェクトを比較し、異なればpass
chai.assert.isFalse(bool); // boolがfalseかどうかを比較
chai.assert.isTrue(bool); // boolがtrueかどうかを比較
chai.assert..isUndefined(data);// dataがundefinedならpass
chai.assert.match(actual, /^aiueo/);// 正規表現でaiueoで始まる文字列ならpass
chai.assert.match(actual, /aiueo$/);// 正規表現でaiueoで終わる文字列ならpass

コメント

タイトルとURLをコピーしました