2014-01-20 40 views
3

我想通过使用茉莉花测试一些视图代码。当视图对象处于不同包容状态时,我需要测试某些元素的存在,而不必在每个状态下重复很多代码。DRYing茉莉花嵌套描述块

我已经得到了类NodeView,它代表了一些端点的节点,以便允许用户使用某些行将此节点连接到其他节点。每个节点都放置在一个列(组)中,以便如果将此节点放入第一个组中,则不会显示左端点。如果节点进入最后一个组,它将不会显示正确的端点。我可以用茉莉花中的嵌套描述块来管理这种情况:

var node, subject, model; 

describe("render", function() { 
    beforeEach(function() { 
    model = mockModel(); 
    }); 

    describe("when the node is into first group", function() { 
    beforeEach(function() { 
     model.isInFirstGroup.andReturn(true); 
     model.isInLastGroup.andReturn(false); 

     node = new NodeView(model); 
    }); 

    it("has the left endpoint hidden", function() { 
     expect(node.el.find('.endpoint .left')).toBeHidden(); 
    }); 

    it("has the right endpoint visible", function() { 
     expect(node.el.find('.endpoint .left')).toBeVisible(); 
    }); 
    }); 

    describe("when the node is into last group", function() { 
    beforeEach(function() { 
     model.isInFirstGroup.andReturn(false); 
     model.isInLastGroup.andReturn(true); 

     node = new NodeView(model); 
    }); 

    it("has the left endpoint visible", function() { 
     expect(node.el.find('.endpoint .left')).toBeVisible(); 
    }); 

    it("has the right endpoint hidden", function() { 
     expect(node.el.find('.endpoint .left')).toBeHidden(); 
    }); 
    }); 

到目前为止一切正常。当我们有其他不同的状态时,麻烦就开始了,在这种情况下,这个状态是允许输入的。这是一个布尔值,表示用户是否可以画线。如果这个布尔值为true,那么节点必须包含一个'输入'类和其他东西。下面是代码(再次渲染功能):

describe("when the node is in input state", function() { 
    beforeEach(function() { 
    model.input = true; 
    node = new NodeView(model); 
    }); 

    it("has the class input", function(){ 
    expect(node.el).toHaveClass('input'); 
    }); 
}); 

describe("when the node is not in input state", function() { 
    beforeEach(function() { 
    model.input = false; 
    node = new NodeView(model); 
    }); 

    it("has not the class input", function(){ 
    expect(node.el).not.toHaveClass('input'); 
    }); 
}); 

好了,好了,林建设一个节点时,测试生成的HTML标记(不调用渲染方法明确),但它确实在内部这项工作。当构建对象时(构造函数调用render),将调用Render,这就是为什么Im不在代码中明确调用node.render()。

测试这些不同的状态将需要测试,包括所有可能的情况:

  • 第一组 - 输入
  • 最后一组 - 输入
  • 第一组 - 没有输入
  • 最后一组 - 无输入

如果我添加另一个布尔状态,那么我有8个场景,依此类推。我试图通过使用共享的例子http://pivotallabs.com/drying-up-jasmine-specs-with-shared-behavior/清理一点点

sharedExamplesForGroupState = function() { 
    describe("(shared)", function() { 
    describe("when the node is into first group", function() { 
     beforeEach(function() { 
     model.isInFirstGroup.andReturn(true); 
     model.isInLastGroup.andReturn(false); 

     node = new NodeView(model); 
     }); 

     it("has the left endpoint hidden", function() { 
     expect(node.el.find('.endpoint .left')).toBeHidden(); 
     }); 

     it("has the right endpoint visible", function() { 
     expect(node.el.find('.endpoint .left')).toBeVisible(); 
     }); 
    }); 

    describe("when the node is into last group", function() { 
     beforeEach(function() { 
     model.isInFirstGroup.andReturn(false); 
     model.isInLastGroup.andReturn(true); 

     node = new NodeView(model); 
     }); 

     it("has the left endpoint visible", function() { 
     expect(node.el.find('.endpoint .left')).toBeVisible(); 
     }); 

     it("has the right endpoint hidden", function() { 
     expect(node.el.find('.endpoint .left')).toBeHidden(); 
     }); 
    }); 
    }); 
}); 

describe("when the node is in input state", function() { 
    beforeEach(function() { 
    model.input = true; 
    node = new NodeView(model); 
    }); 

    it("has the class input", function(){ 
    expect(node.el).toHaveClass('input'); 
    }); 

    sharedExamplesForGroupState(); 
}); 

describe("when the node is not in input state", function() { 
    beforeEach(function() { 
    model.input = false; 
    node = new NodeView(model); 
    }); 

    it("has not the class input", function(){ 
    expect(node.el).not.toHaveClass('input'); 
    }); 

    sharedExamplesForGroupState(); 
}); 
上面没有按预期的方式输入状态测试没有设定输入状态进行工作,所以

线,我们真正测试:

  • 输入和没有输入独立的基团的
  • 而不包括输入测试的情况下,但其中包括model.input属性
第一和最后一组

这并不是真正测试所有4种情况。

有关如何改进这一点以避免指数重复代码的任何想法?

非常感谢。

回答

2

我认为您的最新describe块上的beforeEach正在注册的回调函数正在被sharedExamplesForGroupState()调用的beforeEach调用覆盖。如果为sharedExamplesForGroupState调用创建了一个新的作用域(如将其封装到describe块中),它应该可以工作:

describe("when the node is in input state", function() { 
    beforeEach(function() { 
    model.input = true; 
    node = new NodeView(model); 
    }); 

    it("has the class input", function(){ 
    expect(node.el).toHaveClass('input'); 
    }); 

    describe("shared examples for group state", function() { 
    sharedExamplesForGroupState(); 
    }); 
}); 
+0

这是代码示例中的错误。我已经修好了。这个问题更像是如何在尝试测试状态时避免测试用例重复,这些状态需要一些初始设置必须在嵌套的beforeEach块中完成。也许我可以解决它从共享示例中删除所有beforeEach块,并让最顶级的测试声明为每个组合进行所需的设置。 – Ungue