我正在学习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

最佳答案

在第一个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
     ...

缺点是,对于helper中的每个属性,都必须这样做,最后还要做一些工作。但是,如果您主要关心的是消除spec文件中的重复,这将有所帮助。
我不知道这是多么地道。我通常在spec文件中启动新的对象进行验证测试(spec_helper通常处理多个步骤的过程,比如单击下拉菜单、填写文本,然后单击“提交”),但可能您的验证比我通常的要多。
更新
我正在做一个项目,只是翻阅了我参加的代码学校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以确保加载共享示例。
这真的会让你的代码干涸,但我个人会有点担心可读性。我想如果你用一个足够描述性的名字来描述你的共享示例,你会没事的。

关于ruby-on-rails - 如何使Rails的RSpec测试干燥,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15773874/

10-15 19:39