摩卡嵌套/复制测试

时间:2015-07-15 21:36:24

标签: javascript node.js testing mocha

给定满足某些不变量的数据结构,我想在各种操作之后测试数据结构实例的状态。这样做的最佳方式是什么?

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

2 个答案:

答案 0 :(得分:0)

以下是一个例子,如果我忘记了我们讨论的内容,请告诉我:

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
});

这段代码可以让您了解哪些实例可以访问以及在哪里。 如果它缺少某些东西,请告诉我,我会去解决它。

答案 1 :(得分:0)

问题

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,但是当测试afterEach运行后two挂钩发生故障时,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被标记为失败,Mocha继续运行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 () {
    });
});

这将产生与前一代码片段相同的输出。