初認識フロントエンドテスト3--mocha

12009 ワード

mocha


第1節のテストではmochaフレームワークを用いたが,この節ではmochaフレームワークについて述べる.以下に整理する内容は主に公式サイトから来ています.詳細についてはmocha公式サイトに移動してください.
mochaは機能豊富なフロントエンドテストフレームワークであり、mochaはNodeに基づいてもよい.js環境実行は、ブラウザ環境でプロジェクトアドレスを実行することもできます.
Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.

インストール


インストールには2つの方法があります.1.グローバルインストール;2.mochaをプロジェクト依存モジュールとしてインストールします.
npm install --global mocha
npm install --save-dev mocha

スタート


テストスクリプトの書き方


Mochaの役割はテストスクリプトを実行することであり,まずテストスクリプトを書くことを学ばなければならない.「テストスクリプト」とは、ソースコードをテストするためのスクリプトです.次は加算モジュールaddです.jsのコード.
// add.js
function add(x, y) {
  return x + y;
}

module.exports = add;

この加算モジュールが正しいかどうかをテストするには、テストスクリプトを書きます.通常、テストスクリプトは、テストするソースコードスクリプトと同名であるが、接尾辞名は.test.js(テストを表す)または.spec.js(仕様を示す).例えばadd.jsのテストスクリプトの名前はaddです.test.js.
// add.test.js
var add = require('./add.js');
var expect = require('chai').expect;

describe(' ', function() {
  it('1   1   2', function() {
    expect(add(1, 1)).to.be.equal(2);
  });
});

上のコードは、独立して実行できるテストスクリプトです.テストスクリプトには、1つ以上のdescribeブロックが含まれ、各describeブロックには1つ以上のitブロックが含まれる必要があります.
describeブロックは、関連するテストのセットを表す「テストスイート」(test suite)と呼ばれます.これは関数で、最初のパラメータはテストスイートの名前(「加算関数のテスト」)で、2番目のパラメータは実際に実行される関数です.
itブロックは「テスト例」(test case)と呼ばれ、単独のテストを表し、テストの最小単位である.これも関数です.最初のパラメータはテスト例の名前(「1に1を足すと2になるはずです」)で、2番目のパラメータは実際に実行される関数です.

アサーション・ライブラリ


上のテストスクリプトには、断言があります.
expect(add(1, 1)).to.be.equal(2);

「断言」とは,ソースコードの実際の実行結果が予想結果と一致するか否かを判断し,一致しなければ誤りを投げ出すことである.上の断言の意味はadd(1,1)を呼び出し,結果は2に等しいはずである.すべてのテスト・インスタンス(itブロック)には、1つ以上の文の断言が含まれている必要があります.これはテスト例を作成する鍵です.アサーション機能はアサーションライブラリによって実現され,Mocha自体はアサーションライブラリを持たないため,まずアサーションライブラリを導入しなければならない.
var expect = require('chai').expect;

断言ライブラリには多くの種類がありますが、Mochaはどちらを使用するかを制限しません.これにより、任意の断言ライブラリを使用できます.上記のコードで導入されたブレークスルーライブラリはchaiであり、そのexpectブレークスルースタイルを指定します.次の一般的なブレークスルー・ライブラリは、次のとおりです.
  • assertこれはNodeです.jsのブレークスルーモジュール.
  • should.js
  • expect.js
  • chaijs
  • better-assert
  • unexpected.js

  • expect断言の利点は自然言語に近いことであり,以下にいくつかの例を示す.
    //  
    expect(4 + 5).to.be.equal(9);
    expect(4 + 5).to.be.not.equal(10);
    expect(foo).to.be.deep.equal({ bar: 'baz' });
    
    //  true
    expect('everthing').to.be.ok;
    expect(false).to.not.be.ok;
    
    // typeof
    expect('test').to.be.a('string');
    expect({ foo: 'bar' }).to.be.an('object');
    expect(foo).to.be.an.instanceof(Foo);
    
    // include
    expect([1, 2, 3]).to.include(2);
    expect('foobar').to.contain('foo');
    expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
    
    // empty
    expect([]).to.be.empty;
    expect('').to.be.empty;
    expect({}).to.be.empty;
    
    // match
    expect('foobar').to.match(/^foo/);
    

    基本的にexpect断言の書き方は同じです.頭部はexpect法であり,末尾はequal,a/an,ok,matchなどの断言法である.両者の間にtoまたはtoを用いる.be接続.expectが成立しないと断言すると、間違いが投げ出されます.実際には、エラーを投げ出さない限り、テスト例は合格します.
    it('1   1   2', function() {});
    

    上のこのテスト例は、内部にコードがなく、エラーが投げ出されていないので合格します.

    コマンドラインでmochaを使用する


    コマンドラインでmochaを使用するには、グローバルにインストールする必要があります:npm install mocha -g、指定したファイルをいくつかのパラメータでテストしたり、結果を表示するスタイルを指定したり、テストレポートをエクスポートしたりすることができます.mocha --helpコマンドを使用して、すべてのパラメータを表示できます.

    プロジェクトでmochaを使用する


    nodeプロジェクトを初期化
    mkdir step1 && cd step1
    npm init -y
    npm install --save-dev mocha
    

    フォルダtestを作成し、その中にtestを作成します.js、次の内容を書きます.
    次のコードは、配列[1, 2, 3]indexOf()メソッドを主に簡単にテストします.[1, 2, 3].indexOf(4)は-1を返すと予想されています.
    var assert = require('assert');
    describe('Array', function() {
      describe('#indexOf()', function() {
        it('should return -1 when the value is not present', function() {
          assert.equal([1, 2, 3].indexOf(4), -1);
        });
      });
    });
    

    パッケージを変更します.jsonファイル.
    {
      "scripts": {
        "test": "mocha"
      }
    }
    

    次に端末を開き、コマンドラインでnpm run testを実行し、以下は実行結果である.
    image.png

    mocha基礎用法


    テストコールバックメソッドが複数回呼び出されました


    コールバックベースの非同期テストを使用する場合、done()が複数回呼び出されると、Mochaはエラーを放出します.これは意外な二重コールをキャプチャするのに便利です.
    it('double done', function(done) {
      // Calling `done()` twice is an error
      setImmediate(done);
      setImmediate(done);
    });
    

    複数回の予期せぬ実行エラーの結果をコールバック
    image.png

    非同期コードチェック


    Mochaを使用して非同期コードをテストするのは簡単です!テストが完了したときにコールバックを呼び出すだけです.コールバック関数(通常done)を追加することで、Mochaはこの関数が呼び出されるのを待ってテストを完了する必要があることを知っています.コールバックは、Errorインスタンス(またはそのサブクラス)または偽造値を受け入れる.他の何事もテストに失敗します.
    describe('User', function() {
      describe('#save()', function() {
        it('should save without error', function(done) {
          var user = new User('Luna');
          user.save(function(err) {
            if (err) done(err);
            else done();
          });
        });
      });
    });
    

    より簡単にするためにdone()コールバック関数もErrorインスタンス(すなわち新しいError()を受け入れるので、直接使用することができます.
    describe('User', function() {
      describe('#save()', function() {
        it('should save without error', function(done) {
          var user = new User('Luna');
          user.save(done);
        });
      });
    });
    

    Promiseの実行


    または、done()コールバックを使用せずにPromiseを返すことができます.これは、テスト中のAPIがコールバックではなくPromiseを返す場合に便利です.
    beforeEach(function() {
      return db.clear().then(function() {
        return db.save([tobi, loki, jane]);
      });
    });
    
    describe('#find()', function() {
      it('respond with matching records', function() {
        return db.find({ type: 'User' }).should.eventually.have.length(3);
      });
    });
    

    async/awaitの使用


    JS環境が非同期/待機をサポートしている場合は、このような非同期テストを作成することもできます.
    beforeEach(async function() {
      await db.clear();
      await db.save([tobi, loki, jane]);
    });
    
    describe('#find()', function() {
      it('responds with matching records', async function() {
        const users = await db.find({ type: 'User' });
        users.should.have.length(3);
      });
    });
    

    同期コードのテスト


    同期コードをテストするときはコールバックを省略し、mochaは自動的に次のテストを続行します.
    describe('Array', function() {
      describe('#indexOf()', function() {
        it('should return -1 when the value is not present', function() {
          [1, 2, 3].indexOf(5).should.equal(-1);
          [1, 2, 3].indexOf(0).should.equal(-1);
        });
      });
    });
    

    矢印関数


    mochaで矢印関数を使用することは奨励されません.式にバインドされているthisは、mochaコンテキストにアクセスできません.たとえば、次のコードは失敗します.
    describe('my suite', () => {
      it('my test', () => {
        // should set the timeout of this test to 1000 ms; instead will fail
        this.timeout(1000);
        assert.ok(true);
      });
    });
    

    mochaのコンテキストを使用する必要がない場合は、式は正常に動作します.しかし、最終的に再構築が必要な場合は、予想とは異なる結果になる可能性があります.

    フック本


    Mochaは、デフォルトの「BDD」スタイルのインタフェースで、before()、after()、beforeEach()、afterEach()の前のフックを提供します.これらは、前提条件を設定し、テスト後にクリーンアップするために使用する必要があります.
    describe('hooks', function() {
      before(function() {
        // runs before all tests in this block
      });
    
      after(function() {
        // runs after all tests in this block
      });
    
      beforeEach(function() {
        // runs before each test in this block
      });
    
      afterEach(function() {
        // runs after each test in this block
      });
    
      // test cases
    });
    

    テストはフックの前に、後に、または挿入して現れます.状況によっては、フックは定義された順序で実行されます.すべてのbefore()フックが(1回)、その後、任意のbeforeEach()フック、テスト、任意のafterEach()フック、および最後のafter()フック(1回).

    フックの説明


    任意のフックは、オプションの説明で呼び出すことができ、テスト中のエラーを容易に特定できます.フックに名前付き関数が付与されている場合、説明が指定されていない場合は、この名前が使用されます.
    beforeEach(function() {
      // beforeEach hook
    });
    
    beforeEach(function namedFun() {
      // beforeEach:namedFun
    });
    
    beforeEach('some description', function() {
      // beforeEach:some description
    });
    

    ひどうきフック


    すべてのフック(before()、after()、beforeEach()、afterEach()は同期または非同期であり、その動作は従来のテストケースと非常に似ている.たとえば、次のコードでは、テストのたびに仮想コンテンツでデータベースを埋め込むことができます.
    describe('Connection', function() {
      var db = new Connection(),
        tobi = new User('tobi'),
        loki = new User('loki'),
        jane = new User('jane');
    
      //  
      beforeEach(function(done) {
        db.clear(function(err) {
          if (err) return done(err);
          db.save([tobi, loki, jane], done);
        });
      });
    
      describe('#find()', function() {
        it('respond with matching records', function(done) {
          db.find({ type: 'User' }, function(err, res) {
            if (err) return done(err);
            res.should.have.length(3);
            done();
          });
        });
      });
    });
    

    rootレベルのフック


    任意のファイルを選択してrootレベルのフックを追加することもできます.たとえば、すべてのdescribe()ブロックの外にbeforeEach()を追加します.ここで定義したコールバックbeforeEach()は、どのファイルに存在するかにかかわらず、任意のテスト・インスタンスの前に実行されます(これは、Mochaが「rootスイート」と呼ばれる隠れたdescribe()ブロックを持っているためです).
    beforeEach(function() {
      console.log('before every test in every file');
    });
    

    rootスイートの実行を遅らせる


    任意のスイートを実行する前に非同期操作を実行する必要がある場合は、rootスイートが遅延する可能性があります.--delayフラグでmochaを実行します.これにより、グローバルコンテキストに特殊なコールバック関数run()が追加されます.
    setTimeout(function() {
      // do some setup
    
      describe('my suite', function() {
        // ...
      });
    
      run();
    }, 5000);
    

    保留中のテスト例


    保留中のテスト・インスタンスとは、最終的に完了する必要があり、完了する必要があるテストのインスタンスを指し、これらのインスタンスは説明のみでコールバックされません.テスト対象はテスト結果に含まれ、処理対象としてマークされます.未解決のテストは失敗したテストと見なされません.次のようにします.
    describe('Array', function() {
      describe('#indexOf()', function() {
        // pending test below
        it('should return -1 when the value is not present');
      });
    });
    

    実行結果
    image.png

    テストケース管理


    多くのテスト例がある場合.時には、そのうちのいくつかだけを実行したい場合があります.この場合、onlyメソッドを使用することができます.describeブロックとitブロックは、onlyメソッドを呼び出すことを許可し、テストスイートまたはテストインスタンスのみを実行することを示します.
    describe('Array', function() {
      describe.only('#indexOf()', function() {
        // ...
      });
    });
    
    describe('Array', function() {
      describe('#indexOf()', function() {
        it.only('should return -1 unless present', function() {
          // ...
        });
    
        it('should return the index when present', function() {
          // ...
        });
      });
    });
    

    skipメソッドを使用するには、いくつかのテスト例をスキップする必要がある場合があります.
    describe('Array', function() {
      describe.skip('#indexOf()', function() {
        // ...
      });
    });
    
    describe('Array', function() {
      describe('#indexOf()', function() {
        it.skip('should return -1 unless present', function() {
          // this test will not be run
        });
    
        it('should return the index when present', function() {
          // this test will be run
        });
      });
    });
    

    環境に応じてインスタンスをスキップまたは指定して実行するかどうかを判断する必要がある場合があります.次のコードを参照してください.
    it('should only test in the correct environment', function() {
      if (/* check test environment */) {
        // make assertions
      } else {
        this.skip();
      }
    });
    
    it('should only test in the correct environment', function() {
      if (/* check test environment */) {
        // make assertions
      } else {
        // do nothing
      }
    });
    
    before(function() {
      if (/* check test environment */) {
        // setup code
      } else {
        this.skip();
      }
    });