Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 什么';使用Jasmine重用测试代码的好方法是什么?_Javascript_Bdd_Jasmine - Fatal编程技术网

Javascript 什么';使用Jasmine重用测试代码的好方法是什么?

Javascript 什么';使用Jasmine重用测试代码的好方法是什么?,javascript,bdd,jasmine,Javascript,Bdd,Jasmine,我正在使用BDD Javascript库,并且非常喜欢它。我有我想重用的测试代码(例如,测试一个基类的多个实现或在稍微不同的上下文中运行相同的测试),我不知道如何使用Jasmine来完成。我知道我可以将代码从jasmine函数中移出并放入可重用类中,但我喜欢代码读起来与jasmine函数(descripe,it)交织在一起的方式,我不想将规范与测试代码分开,除非我不得不这样做。有没有人在使用Jasmine时遇到过这个问题?您是如何处理的?有人向我指出,要在传递参数的函数中封装描述调用。这里是Pi

我正在使用BDD Javascript库,并且非常喜欢它。我有我想重用的测试代码(例如,测试一个基类的多个实现或在稍微不同的上下文中运行相同的测试),我不知道如何使用Jasmine来完成。我知道我可以将代码从jasmine函数中移出并放入可重用类中,但我喜欢代码读起来与jasmine函数(descripe,it)交织在一起的方式,我不想将规范与测试代码分开,除非我不得不这样做。有没有人在使用Jasmine时遇到过这个问题?您是如何处理的?

有人向我指出,要在传递参数的函数中封装描述调用。

这里是Pivotal Labs的一位同事写的一篇文章,详细介绍了如何封装描述调用:

文章中显示部分包装函数的代码段:

function sharedBehaviorForGameOf(context) {
  describe("(shared)", function() {
    var ball, game;
    beforeEach(function() {
      ball = context.ball;
      game = context.game;
    });
  });
}

我不确定@starmer的解决方案是如何工作的。正如我在评论中提到的,当我使用他的代码时,
上下文总是未定义的

相反,您必须做的(正如@moefinley所提到的)是将引用传递给构造函数。我已经用一个例子概括了这种方法。以下是它的精髓:

describe('service interface', function(){
    function createInstance(){
        return /* code to create a new service or pass in an existing reference */
    }

    executeSharedTests(createInstance);
});

function executeSharedTests(createInstanceFn){
    describe('when adding a new menu entry', function(){
        var subjectUnderTest;

        beforeEach(function(){
            //create an instance by invoking the constructor function
            subjectUnderTest = createInstanceFn();
        });

        it('should allow to add new menu entries', function(){
            /* assertion code here, verifying subjectUnderTest works properly */
        });
    });
}

thoughbot的网站上有一篇很好的文章:

以下是一个简单的示例:

appNamespace.jasmine.sharedExamples = {
  "rectangle": function() {
    it("has four sides", function() {
      expect(this.subject.sides).toEqual(4);
    });
  },
 };
并使用一些下划线函数来定义
其行为应类似

window.itShouldBehaveLike = function() {
  var exampleName      = _.first(arguments),
      exampleArguments = _.select(_.rest(arguments), function(arg) { return !_.isFunction(arg); }),
      innerBlock       = _.detect(arguments, function(arg) { return _.isFunction(arg); }),
      exampleGroup     = appNamespace.jasmine.sharedExamples[exampleName];

  if(exampleGroup) {
    return describe(exampleName, function() {
      exampleGroup.apply(this, exampleArguments);
      if(innerBlock) { innerBlock(); }
    });
  } else {
    return it("cannot find shared behavior: '" + exampleName + "'", function() {
      expect(false).toEqual(true);
    });
  }
};

这与starmer的答案相似,但经过研究,我发现了一些不同之处。缺点是,如果规范失败,您只需在Jasmine报告中看到“应该遵守常见的保存规范”。堆栈跟踪是找到失败位置的唯一方法

// common specs to execute
self.executeCommonSpecifications = function (vm) {
  // I found having the describe( wrapper here doesn't work
  self.shouldCallTheDisplayModelsSaveMethod(vm);
}
self.shouldCallTheDisplaysSaveMethod = function (vm) {
  expect(vm.save.calls.count()).toBe(1);
};

// spec add an it so that the beforeEach is called before calling this
beforeEach(function(){
  // this gets called if wrapped in the it
  vm.saveChanges();
}
it('should adhere to common saving specifications', function () {
  executeSavingDisplaysCommonSpecifications(vm);
});

受本文启发,我采取了以下方法:

基于Jasmine自己的文档:

通过将共享依赖项设置为
beforeach
函数原型的属性,可以扩展
beforeach
以通过
this
使此依赖项可用

例如:

describe('A suite', function() {
    // Shared setup for nested suites
    beforeEach(function() {
        // For the sake of simplicity this is just a string
        // but it could be anything
        this.sharedDependency = 'Some dependency';
    });

    describe('A nested suite', function() {
        var dependency;

        beforeEach(function() {
            // This works!
            dependency = this.sharedDependency;                
        });

        it('Dependency should be defined', function() {
            expect(dependency).toBeDefined();
        });
    });

    describe('Check if string split method works', function() {
        var splitToArray;

        beforeEach(function() {
            splitToArray = this.sharedDependency.split();                
        });

        it('Some other test', function() { ... });
    });
});
我知道我的示例有点无用,但它应该作为代码示例发挥作用

当然,这只是实现你所说的许多事情中的一件,我相信更复杂的设计模式可能会应用在这个上面或旁边


希望有帮助

让我用工作示例来总结一下

描述('test',函数(){
beforeach(函数(){
此参数为1;
});
它('应该测试共享',函数(){
期望(这个。共享)。toBe(1);
});
testShared();
});
函数testShared(){
它('应该在函数中测试',函数(){
期望(这个。共享)。toBe(1);
});
}
这里的关键部分是传递上下文的这个关键字,因此我们必须使用“正常”函数(另一个关键部分)

对于生产代码,我可能只在每个
之前的
中使用普通函数来传递/提取上下文,但为了简洁起见,请在规范中使用箭头函数

将上下文作为参数传递将不起作用,因为通常我们在每次调用之后调用的
块之前定义上下文


拥有
描述
部分似乎并不重要,但仍然欢迎更好的结构

这里有一个更简单的解决方案。 声明变量函数并使用它,而不使用this关键字或上下文:

describe("Test Suit", function ()
{
   var TestCommonFunction = function(inputObjects)
   {
     //common code here or return objects and functions here etc
   };

   it("Should do x and y", function()
   {
       //Prepare someInputObjects
       TestCommonFunction(someInputObjects);
       //do the rest of the test or evaluation
   });
});

您还可以返回一个包含更多函数的对象,然后调用返回的函数。

您至少应该粘贴一个片段,该片段正是@starmer回答的内容,您可能希望更改您接受的答案当我尝试本文中的代码时,传递的范围(篮球或足球)在beforeach函数运行之前传入,因此是空对象。我通过传入一个构造函数实例解决了这个问题。但我仍然好奇戴维斯的代码是如何工作的。我遗漏了什么吗?这里也一样……对象未定义,因为之前的
尚未执行。您是否找到了其他解决方案@moefinley???@Juri传入构造函数实例有什么问题?如果对象未定义,请尝试用它包装函数调用,例如它('blah',function(){sharedBehaviorForGameOf(football);});我想页面已经移到这里,看看下面我的答案,如何通过它传递上下文