如何干掉Rails的RSpec测试

时间:2013-04-02 20:36:40

标签: ruby-on-rails ruby rspec

我正在学习RSpec,我不禁注意到我的代码中有很多重复。以下只是其他许多例子中的两个例子。有没有办法创建共享测试而无需遍历每个属性?

  describe "validation" do
    describe "user_id" do
      it "should not be blank or nil" do
        @comment.user_id = nil
        @comment.should_not be_valid
        @comment.user_id = " "
        @comment.should_not be_valid
      end

      it "should an integer" do
        @comment.user_id = "a"
        @comment.should_not be_valid        
      end
    end

    describe "post_id" do
      it "should not be blank or nil" do
        @comment.post_id = nil
        @comment.should_not be_valid
        @comment.post_id = " "
        @comment.should_not be_valid
      end

      it "should an integer" do
        @comment.post_id = "a"
        @comment.should_not be_valid        
      end      
    end
  end

3 个答案:

答案 0 :(得分:5)

您可以尝试:https://github.com/thoughtbot/shoulda-matchers

它为您的模型提供了许多简单的匹配器

答案 1 :(得分:3)

在第一个describe区块中,您可以将主题设置为@comment.user_id,如下所示:

describe "validation" do
  describe "user_id" do
    before { @comment = Comment.create } # or however you want to initialize your comment     
                                         # (FactoryGirl is commonly used)
    subject { @comment.user_id }

    it "should not be blank or nil" do
      before { @comment.user_id = nil }           #I edited this to make it clearer.
      it { should_not be_valid }

      before { @comment.user_id = " " }
      it { should_not be_valid }
    end
    ...

这使得它干涸了一些,让我觉得它更具可读性。显然你可以把剩下的东西模仿我在这里所拥有的东西。


编辑:这不会保存很多字符(实际上你最后输入的内容更多),但它确实消除了spec文件本身中@comment.{attrbute} = whatever的重复。您可以为每个赋值定义一个帮助程序,如下所示:

/spec/helpers/comment_spec_helper.rb
def user_id nil
  @comment.user_id = nil
end

....

为每个属性执行此操作。然后在您的规范中:

    subject { @comment.user_id }

    it "should not be blank" do
      before { user_id nil }         
      it { should_not be_valid }

    it "should not be nil" do
     ...

缺点是,你必须为助手中的每个属性做到这一点,最后你还要做更多的工作。但如果您主要关注的是消除spec文件中的重复,这将有所帮助。

我不知道这是多么惯用。我通常在spec文件中启动新对象以进行验证测试,(我的spec_helper通常会处理多步骤过程,例如单击下拉菜单,填写文本,然后单击“提交”),但也许你有比我通常更多的验证。


更新

我正在研究一个项目,刚刚翻过我所参加的Codeschool的RSpec课程的笔记,我想我会建议共享的例子。他们给出的例子是:

describe Zombie do
  it_behaves_like ‘the undead’, Zombie.new
end

describe Vampire do
  it_behaves_like ‘the undead’, Vampire.new
end

shared_examples_for ‘the undead’ do |undead|
  it ‘does not have a pulse’ do
    undead.pulse.should == false
  end
end

这似乎是适用的,但您必须牢记某些conventions以确保加载了共享示例。

这会真的干掉你的代码,但我个人会对可读性有点担心。我想如果你为共享的例子使用一个描述性足够的名字,你就可以了。

答案 2 :(得分:1)

您可以使用工厂(例如FactoryGirl):

build(:comment, user_id: nil).should_not be_valid