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

我正在使用Jasmine BDD Javascript库并且非常享受它。我有测试代码,我想重用(例如,测试基类的多个实现或在稍微不同的上下文中运行相同的测试),我不知道如何使用Jasmine。我知道我可以将代码从jasmine函数移到可重用的类中,但我喜欢代码读取散布Jasmine函数的方式(描述,它),我不想将规范与测试代码分开,除非我不得不。有没有人使用Jasmine遇到这个问题,你是如何处理它的?     
已邀请:
以下是Pivotal Labs的一篇文章,其中详细介绍了如何打包描述调用: 用共享行为干掉Jasmine规范 文章中显示部分包装函数的片段:
function sharedBehaviorForGameOf(context) {
  describe("(shared)", function() {
    var ball, game;
    beforeEach(function() {
      ball = context.ball;
      game = context.game;
    });
  });
}
    
我不确定@ starmer的解决方案是如何运作的。正如我在评论中提到的,当我使用他的代码时,
context
总是未定义的。 相反,你必须做的事情(如@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 */
        });
    });
}
    
关于butbot的网站上有一篇很好的文章:https://robots.thoughtbot.com/jasmine-and-shared-examples 这是一个简短的例子:
appNamespace.jasmine.sharedExamples = {
  "rectangle": function() {
    it("has four sides", function() {
      expect(this.subject.sides).toEqual(4);
    });
  },
 };
并使用一些下划线功能来定义
itShouldBehaveLike
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);
});
    
这是我采取的方法,受到本文的启发: https://gist.github.com/traviskaufman/11131303 这是基于Jasmine自己的文档: http://jasmine.github.io/2.0/introduction.html#section-The_%3Ccode%3Ethis%3C/code%3E_keyword 通过将共享依赖项设置为
beforeEach
函数原型的属性,您可以扩展
beforeEach
以通过
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() { ... });
    });
});
我知道我的例子有点无用,但它应该作为代码示例服务于它的目的。 当然,这只是你可以做的很多事情之一,你可以做到这一点,我确信更复杂的设计模式可以应用于顶部或旁边。 希望能帮助到你!     
让我用工作实例来总结一下
  describe('test', function () {

    beforeEach(function () {
      this.shared = 1;
    });

    it('should test shared', function () {
      expect(this.shared).toBe(1);
    });

    testShared();
  });

  function testShared() {
    it('should test in function', function() {
      expect(this.shared).toBe(1);
  });

  }
这里的关键部分是传递上下文的关键字,因此我们必须使用“普通”函数(另一个关键部分)。 对于生产代码,我可能只在
beforeEach
中使用普通函数来传递/提取上下文,但为了简洁起见,在规范中继续使用箭头函数。 将上下文作为参数传递是行不通的,因为通常我们在之后调用的
beforeEach
块中定义上下文。 有
describe
部分似乎并不重要,但仍然欢迎更好的结构     
有人指出我将一个describe调用包装在一个传递参数的函数中。     

要回复问题请先登录注册