8

it() 関数内に何も期待されていない場合にテストを失敗として報告するように mocha を設定するオプションはありますか?

アイデアは、次のようなワークフローです。

  1. des() とコールバック関数を使用して it() を 1 つ追加します。
  2. コールバックで期待値が設定されていないため、 it() は失敗として報告されます
  3. 期待が加わる
  4. it() はまだ実装されていないため、期待が満たされていないため、失敗として報告されます
  5. 実装が追加されました
  6. it() は成功として報告されます
  7. リファクタリング

したがって、主な意図は、標準的なTDDスタイルの開発を行っている間、新しく追加されたテストが期待値が設定されるまで失敗したと報告されることです(またはコールバックまたはskip()なしで保留中として設定されたテスト)。これは再び失敗として報告され、実装が完了すると次のように報告されます成功。

it() が期待せずに成功することの価値は、追加されると失敗することで、実際に機能していることを証明し、失敗していることを証明することです。それは意図的なものでしたか、それとも何かが欠けていますか?

また、誰かが karma.conf.js でそれを設定する方法を知っているなら、それは素晴らしいことです.

ありがとう

4

4 に答える 4

2

モカはフラグを立てただけではやりたいことをサポートしてくれません。最も近いのはit、コールバックなしで使用することです:

`it("foo")`

Mocha はこのテストを扱い、pendingそのように報告します。を使用するのと同じit.skip(...)です。ただし、テストは失敗せず、実際には繰り返されないループがあるなどの愚かな間違いを検出しません。

it("foo", function () {
    var a = something();
    for (var i = 0; i < a.length; ++i) {
        expect(a[i]).to...
    }
});

長さ 0 の配列が発生した場合aは、何もテストせず、テストに合格します。このような場合、配列の長さが 0 ではないことをテストしますが、それでも...

したがって、それを行う直接的な方法はなく、Mocha はアサーション ライブラリがフックして、テストで実際に使用されたことを Mocha に伝えるための API を提供していません。ただし、独自のソリューションを構築できます。概念実証は次のとおりです。

var real_expect = require("chai").expect;

var expect_called = 0;

function expect() {
    expect_called++;
    return real_expect.apply(this, arguments);
}

var real_it = it;

it = function (name, fn) {
    if (!fn.length) {
        // Handle the case where `fn` is declared to be synchronous.
        real_it(name, function () {
            expect_called = 0;
            fn.call(this);
            if (expect_called === 0)
                throw new Error("test did not call expect");
        });
    }
    else {
        // Handle the case where `fn` is declared to be asynchronous.
        real_it(name, function (real_done) {
            expect_called = 0;
            function done () {
                if (expect_called === 0) {
                    done(new Error("test did not call expect"));
                    return;
                }
                real_done();
            }
            fn.call(this, done);
        });
    }
};

it("foo", function () {
    expect(1).to.equal(1);
});

it("foo async", function (done) {
    setTimeout(function () {
        expect(1).to.equal(1);
        done();
    }, 1000);
});

it("bar", function () {});
it("bar 2", function () {});

上記のコードitでは、チェックを行う独自のものに置き換えexpect、呼び出されたときにフラグを立てるために独自のものに置き換えます。

非同期テストと共有状態に関するメモ。非同期としてマークされている場合、Mocha が同時に複数実行されると考える人がいます。通常、これは当てはまりません。Mocha は、非同期テストの後に続行する前に、テストがdoneコールバックを呼び出すか、タイムアウトするかのいずれかを待機します。前のテストがタイムアウトした場合、2 つのテストのコードを同時に実行することができ、タイムアウトしたテストが実際には後で完了する非同期操作を待っていた場合がありますタイムアウト。このような場合、両方のテストが依存する状態があると、タイムアウトにより、カスケード テストの失敗 (またはカスケード テストの成功!) が発生する可能性があります。これは Mocha の一般的な問題です。タイムアウトの問題が修正されると、カスケード効果がなくなり、タイムアウトした以前の非同期テストの影響を受けることなく、後続のテストが成功または失敗するようになります。上記のコードでexpected_calledは、すべてのテストが依存する状態です。そのため、タイムアウトはカスケード効果を引き起こす可能性があります。

この問題を解決するには、各テストに の独自のプライベート インスタンスが必要ですexpect。これは、独自のプライベート カウンタをインクリメントするだけです。これは次のように行うことができます。

var real_expect = require("chai").expect;

var real_it = it;

it = function (name, fn) {
    if (!fn.length) {
        // Handle the case where `fn` is declared to be synchronous.
        real_it(name, function () {
            var expect_called = 0;

            this.expect = function () {
                expect_called++;
                return real_expect.apply(this, arguments);
            };

            fn.call(this);
            if (expect_called === 0)
                throw new Error("test did not call expect");
        });
    }
    else {
        // Handle the case where `fn` is declared to be asynchronous.
        real_it(name, function (real_done) {
            var expect_called = 0;

            this.expect = function () {
                expect_called++;
                return real_expect.apply(this, arguments);
            };

            function done () {
                if (expect_called === 0) {
                    done(new Error("test did not call expect"));
                    return;
                }
                real_done();
            }

            fn.call(this, done);
        });
    }
};

it("foo", function () {
    this.expect(1).to.equal(1);
});

it("foo async", function (done) {
    var me = this;
    setTimeout(function () {
        me.expect(1).to.equal(1);
        done();
    }, 1000);
});

it("bar", function () {});
it("bar 2", function () {});

ただし、欠点は、expectasにアクセスする必要があることですthis.expect。これは、通常とは異なる方法でテストを作成することを意味します。すべてのテストの前にグローバルを設定するexpectと使用する必要がなくなると思うかもしれませんthisが、このアプローチは上で説明したのとまったく同じ問題の対象となります。(テストによって共有されるグローバルな状態は、expectではなくそれ自体になりexpect_calledます。)

于 2015-06-22T16:39:48.657 に答える