簡體   English   中英

摩卡嵌套/復制測試

[英]mocha nesting/replicating tests

給定一個滿足某些不變性的數據結構,我想在進行各種操作后測試該數據結構實例的狀態。 做這個的最好方式是什么?

describe('data-structure', function() {
  var x;

  beforeEach(function() {
    x = getDataStructure();
  });

  describe('satisfies invariants', function() {
    // run tests on 'fresh' x

    it('should ...', function() { 
      // ...
    });

    // ...
  });

  describe('operation 1', function() {
    it('should preserve invariants', function() {
      x.doSomething();
      // run 'satisfies invariants' tests on modified x
    });
  });
});

我曾考慮過使用afterEach掛鈎,但我不認為x保留在那里?

afterEach(function() {
  // somehow run 'satisfies invariants' test
});

也許我可以將'satisfies invariants'重構為一種方法,但是如果mocha可以報告每個操作哪些不變式測試失敗,那就太好了,例如

data-structure
  satisfies invariants
    should satisfy invariant 1 ...
    ...

  operation 1
    should satisfy invariant 1 ...
    ...

  operation 2
    should satisfy invariant 1 ...
    ...

編輯

使用結構

describe('data-structure', function() {
  var x;

  describe('satisfies invariants', function() {
    afterEach(function() {
      it('should satisfy invariant 1', function() { 
        // x.value === a again
        // ...
      });

      // ...
    });

    it('should work after operation 1', function() {
      x = getDataStructure(); // x.value === a
      x.operation1(); // x.value === b
    });

    it('should work after operation 2', function() {
      x = getDataStructure();
      x.operation2();
    });

    // ...
  });
});

似乎沒有保留對x的更改。

下面是一個示例,如果我忘記了我們所討論的內容,請告訴我:

var assert = require('assert');

describe('data-structure', function() {
    var x;

    beforeEach(function() {
        // freshly created data structure for each describe block below
        x = getDataStructure;
    });

    describe('satisfies invariants', function() {
            after(function() {
                // it executes those tests only once after all the it block below
                assert(x); // put your tests here
            });

            it('op 1.1', function() {
                do_something_on(x);
            });

            it('op 1.2', function() {
                // keep in mind that x is the same instance of the previous test
                do_something_else_on(x);
            });

            // so on
    });

    describe('satisfies something else', function() {
            // here you have a new instance of x, because of the outer beforeeach

            after(function() {
                // it executes those tests only once after all the it block within this describe block
                assert(x); // put your tests here
            });

            it('op 2.1', function() {
                do_something_on(x);
            });

            it('op 2.2', function() {
                // keep in mind that x is the same instance of the previous test, but not the one used in 1.2
                do_something_else_on(x);
            });

            // so on
    });

    // so on
});

這段代碼應該使您了解可以訪問哪些實例以及在何處。 如果缺少某些內容,請告訴我,我將去修復它。

問題

Mocha不支持像上一片段一樣將it放入鈎子中。 afterEach是一個鈎子)。 在某些瑣碎的情況下,您可能會得到理想的行為,但這只是運氣。 一旦轉到更復雜的測試套件,您將無法獲得預期的行為。

而且,我建議afterEach在那種測試中是錯誤的地方。 您應該僅使用鈎子來設置和拆除測試環境,而不能在代碼狀態上執行斷言。 Mocha將鈎子中的任何失敗視為“測試套件損壞,中止!”。 而不是測試失敗。 看這個例子,例如:

var assert = require('assert');

describe("test", function () {
    var x;

    beforeEach(function () {
        x = { foo: 'something' };
    });

    afterEach(function () {
        assert(x.foo === 'something');
    });

    it("one", function () {});

    it("two", function () {
        x.foo = 'something else';
    });

    it("three", function () {});
});

從理論上講,沒有理由不應該運行測試three但是如果在運行測試two之后的afterEach掛鈎中發生故障,Mocha只會在此處停止運行測試。 輸出(省略最后的堆棧跟蹤)為:

  test
    ✓ one 
    ✓ two 
    1) "after each" hook


  2 passing (14ms)
  1 failing

注意如何將two標記為通過,但掛鈎失敗。 請注意,甚至從未嘗試過three 一旦鈎子出現故障,摩卡就停在那里。

解決方案

您應該只創建一個從每個測試調用的函數來測試您的不變式。 例如:

var assert = require('assert');

describe("test", function () {
    var x;

    beforeEach(function () {
        x = { foo: 'something' };
    });

    function testInvariant() {
        assert(x.foo === 'something');
    }

    it("one", function () {
        testInvariant();
    });

    it("two", function () {
        x.foo = 'something else';
        testInvariant();
    });

    it("three", function () {
        testInvariant();
    });
});

如果在上面的代碼上運行Mocha,您將得到(再次,省略最終的堆棧跟蹤):

  test
    ✓ one 
    1) two
    ✓ three 


  2 passing (10ms)
  1 failing

two被標記為失敗,摩卡繼續運行three ,這是成功的。

如果不想在每個測試中編寫testInvariant() ,則可以創建一個為您添加它的函數。 例如:

var assert = require('assert');

describe("test", function () {
    var x;

    beforeEach(function () {
        x = { foo: 'something' };
    });

    function makeTest(name, fn) {
        it(name, function () {
            fn();
            assert(x.foo === 'something');
        });
    }

    makeTest("one", function () {
    });

    makeTest("two", function () {
        x.foo = 'something else';
    });

    makeTest("three", function () {
    });
});

這將產生與先前代碼段相同的輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM