使用不同的数据多次运行相同的mocha测试

Tom*_*ado 42 javascript mocha.js

问题

我有几个测试在mocha中做同样的事情.这对我来说,它是重复的,当你希望你的系统可以维护时,这是最糟糕的事情.

var exerciseIsPetitionActive = function (expected, dateNow) {
    var actual = sut.isPetitionActive(dateNow);
    chai.assert.equal(expected, actual);
};

test('test_isPetitionActive_calledWithDateUnderNumSeconds_returnTrue', function () {
    exerciseIsPetitionActive(true, new Date('2013-05-21 13:11:34'));
});

test('test_isPetitionActive_calledWithDateGreaterThanNumSeconds_returnFalse', function () {
    exerciseIsPetitionActive(false, new Date('2013-05-21 13:12:35'));
});
Run Code Online (Sandbox Code Playgroud)

我需要什么

我需要一种方法来将我的重复mocha测试折叠成一个.

例如,在PhpUnit(和其他测试框架)中,您有dataProviders.
在phpUnit中,dataProvider以这种方式工作:

<?php class DataTest extends PHPUnit_Framework_TestCase {
    /**
     * @dataProvider provider
     */
    public function testAdd($a, $b, $c)
    {
        $this->assertEquals($c, $a + $b);
    }

    public function provider()
    {
        return array(
          array(0, 0, 0),
          array(0, 1, 1),
          array(1, 0, 1),
          array(1, 1, 3)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

此处的提供程序将参数注入测试,测试执行所有情况.非常适合重复测试.

我想知道在mocha中是否有类似的东西,例如,类似这样的东西:

var exerciseIsPetitionActive = function (expected, dateNow) {
    var actual = sut.isPetitionActive(dateNow);
    chai.assert.equal(expected, actual);
};

@usesDataProvider myDataProvider
test('test_isPetitionActive_calledWithParams_returnCorrectAnswer', function (expected, date) {
    exerciseIsPetitionActive(expected, date);
});

var myDataProvider = function() {
  return {
      {true, new Date(..)},
      {false, new Date(...)}
  };
};
Run Code Online (Sandbox Code Playgroud)

我已经看过了什么

有一些tecnique被称为共享行为.但它并没有直接用测试套件解决问题,它只是解决了具有重复测试的不同组件的问题.

问题

你知道在mocha中实现dataProviders的任何方法吗?

Kai*_*izo 22

摩卡不提供这方面的工具,但你自己也很容易做到.您只需要在循环内运行测试并使用闭包将数据提供给测试函数:

suite("my test suite", function () {
    var data = ["foo", "bar", "buzz"];
    var testWithData = function (dataItem) {
        return function () {
            console.log(dataItem);
            //Here do your test.
        };
    };

    data.forEach(function (dataItem) {
        test("data_provider test", testWithData(dataItem));
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 这不适合我.我正在使用```describe()```````it()```syntaxe.返回测试函数是否很重要,或者我们可以直接在```testWithData(dataItem)```中进行测试? (2认同)
  • 我必须确保每个额外的 javascript(比如 ```for each```)都在一个 ```it('tests', function(){ /*HERE */ })``` 中。当我对循环内的每个测试使用 ```it()``` 时,我必须将所有内容都包装在 ```describe(...)``` 中。我最终得到了一个层次结构 ```describe &gt; it &gt; forEach &gt; describe &gt; it```,这使得我循环中的所有测试都出现在我的测试结束时,不管它在测试期间何时发生,但它有效。 (2认同)
  • 如果这不是提出这个问题的正确论坛,我很抱歉,但这似乎不起作用,原因如下: - Mocha 似乎没有“suite”或“test(foo)”结构 - 使用这个 *exact * 代码不起作用 - 它出错并显示“套件未定义”。如何声称这是答案?版本:节点 6.6.0、摩卡 3.1.2 (2认同)
  • @Rubicon您需要使用“tdd”接口运行测试。要使用“bdd”,只需将“suite”更改为“describe”,将“test”更改为“it”。您可以在这里阅读更多相关信息:https://mochajs.org/#interfaces (2认同)

Wto*_*wer 18

使用不同数据运行相同测试的基本方法是在提供数据的循环中重复测试:

describe('my tests', function () {
  var runs = [
    {it: 'options1', options: {...}},
    {it: 'options2', options: {...}},
  ];

  before(function () {
    ...
  });

  runs.forEach(function (run) {
    it('does sth with ' + run.it, function () {
      ...
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

before好吧,在所有it的人之前describe.如果您需要使用其中的一些选项before,请不要将它包含在forEach循环中,因为mocha将首先运行所有befores和全部its,这可能是不需要的.你可以把整个describe放在循环中:

var runs = [
  {it: 'options1', options: {...}},
  {it: 'options2', options: {...}},
];

runs.forEach(function (run) {
  describe('my tests with ' + run.it, function () {
    before(function () {
      ...
    });

    it('does sth with ' + run.it, function () {
      ...
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

如果您不希望用多个describes 污染您的测试,您可以使用有争议的模块sinon:

var sinon = require('sinon');

describe('my tests', function () {
  var runs = [
    {it: 'options1', options: {...}},
    {it: 'options2', options: {...}},
  ];

  // use a stub to return the proper configuration in `beforeEach`
  // otherwise `before` is called all times before all `it` calls
  var stub = sinon.stub();
  runs.forEach(function (run, idx) {
    stub.onCall(idx).returns(run);
  });

  beforeEach(function () {
    var run = stub();
    // do something with the particular `run.options`
  });

  runs.forEach(function (run, idx) {
    it('does sth with ' + run.it, function () {
      sinon.assert.callCount(stub, idx + 1);
      ...
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

诗乃感觉很脏但很有效.像leche这样的一些辅助模块是基于sinon的,但可以说引入更多的复杂性是没有必要的.


has*_*nge 5

Leche将这一功能添加到了 Mocha 中。请参阅公告文档

它比简单地循环测试更好,因为如果测试失败,它会告诉您涉及哪个数据集。

更新:

我不喜欢 Leche 的设置,也没有设法让它与 Karma 一起工作,所以最终我将数据提供程序提取到一个单独的文件中。

如果你想使用它,只需获取源码即可。Leche 自述文件中提供了文档,您可以在文件本身中找到其他信息和使用提示。