javascript-使用Karma&Mocha.js对多个用例进行单元测试

我对测试还很陌生,所以这个问题是关于最佳实践以及该测试应该如何编写的.我正在将Karma与Mocha和Chai一起测试Angular.js应用.

我目前正在测试一个函数,该函数计算以特定顺序排列字母组合的方式的数量.它遵循一种模式来从辅音组或元音组中提取字母.

这些是我目前的测试:

describe("should count the number of combinations correctly", function() {
  describe("with 2-item arrays", function() {
    beforeEach(function(){
      scope.vowels = ['a', 'e'];
      scope.consonants = ['b', 'c'];
    })

    it("with 2 letters in pattern", function() {
      scope.pattern = 'CV';
      expect(scope.combinationCounter()).to.equal(4);
    });

    it("with 3 letters in pattern", function() {
      scope.pattern = 'CVC';
      expect(scope.combinationCounter()).to.equal(8);
    });

    it("with 4 letters in pattern", function() {
      scope.pattern = 'CVCV';
      expect(scope.combinationCounter()).to.equal(16);
    });
  });
  describe("with 3-item arrays", function() {
    beforeEach(function(){
      scope.vowels = ['a', 'e', 'i'];
      scope.consonants = ['b', 'c', 'd'];
    })

    it("with 2 letters in pattern", function() {
      scope.pattern = 'CV';
      expect(scope.combinationCounter()).to.equal(9);
    });

    it("with 3 letters in pattern", function() {
      scope.pattern = 'CVC';
      expect(scope.combinationCounter()).to.equal(27);
    });

    it("with 4 letters in pattern", function() {
      scope.pattern = 'CVCV';
      expect(scope.combinationCounter()).to.equal(81);
    });        
  });
});

这些测试有效,并且它们为我提供了有用的错误消息,但是我不禁感到自己在做一些不必要的重复,因为我实际上是在使用不同的值执行相同的测试.

有没有一种方法可以编写这些测试来维护错误消息的结构,但是不需要我写出来

it("with x letters in pattern", function() {
  scope.pattern = 'whatever';
  expect(scope.combinationCounter()).to.equal(y);
});  

每一次?

我想在没有巨大测试文件的情况下测试大量案例,但请保持错误消息的可读性.

编辑:@Stas回答的问题

@Stas给了我正确的答案,那就是使用带有对象的循环来容纳不同的测试用例.但是,由于他的答案是用lodash编写的(我没有使用过),因此我在下面包括了最终的循环代码以供参考.

我在此处循环播放的场景对象与@Stas示例中的对象相同.

for (var x in scenarios) {
  var vowels     = scenarios[x].arrays.vowels;
  var consonants = scenarios[x].arrays.consonants;
  var v = vowels;
  var c = consonants;
  describeStuff();
}

function describeStuff(){ 
  describe("with " + x, function(){
    setLetters(v,c);
  });
}

function setLetters(vowels, consonants){
  describe("("+vowels + ' & ' + consonants + "),", function(){
    beforeEach(function(){
      scope.vowels = vowels;
      scope.consonants = consonants;
    });
    innerLoop();
  });
}

function innerLoop(){
  for (var y in scenarios[x].combinations) {
    var combinations = scenarios[x].combinations;
    var pat = scenarios[x].combinations[y].pattern;
    var res = scenarios[x].combinations[y].result;
    setResults(pat, res);
  }
}

function setResults(p, r){
  var pattern = p;
  var result = r;
  it("with " + p.length + " letters in pattern (" + p + ")", function(){
    scope.pattern = pattern;
    expect(scope.combinationCounter()).to.equal(result);
  });
}

我必须使用相互调用的四个函数链来编写循环,因为在for in循环中使用Mocha的回调语法只会导致将最终测试用例保存到函数变量中.在循环之外定义函数,然后在内部调用它们可以解决此问题.

解决方法:

您可以创建方案对象并为每个循环包装执行(在此示例中,我使用lodash):

describe("should count the number of combinations correctly", function () {

    var scenarios = {
        "2-item arrays": {
            arrays: {
                vowels: ['a', 'e'],
                consonants: ['b', 'c']
            },
            combinations: [
                {pattern: "CV", result: 4},
                {pattern: "CVC", result: 8},
                {pattern: "CVCV", result: 16}
            ]
        },
        "3-item arrays": {
            arrays: {
                vowels: ['a', 'e', 'i'],
                consonants: ['b', 'c', 'd']
            },
            combinations: [
                {pattern: "CV", result: 9},
                {pattern: "CVC", result: 27},
                {pattern: "CVCV", result: 81}
            ]
        }
    };

    _.forEach(scenarios, function (scenario, key) {
        describe("with " + scenario.key, function () {
            beforeEach(function () {
                scope.vowels = scenario.arrays.vowels;
                scope.consonants = scenario.arrays.consonants;
            });

            _.forEach(scenario.combinations, function(combination) {
                it("with " + combination.pattern.length + " letters in pattern", function() {
                    scope.pattern = combination.pattern;
                    expect(scope.combinationCounter()).to.equal(combination.result);
                });
            })
        });
    });
});

这样,您可以添加更多方案,而无需为每个组合重复describe()/ beforeEach()/ it(),它将产生相同的消息.

上一篇:javascript-“待定”测试在Mocha中是什么意思,如何使其通过/失败?


下一篇:boost::fibers::buffered_channel的测试程序