【问题标题】:Conditional tests in Rspec?Rspec中的条件测试?
【发布时间】:2011-10-14 16:49:31
【问题描述】:

有没有办法使用 rspec 有条件地对测试进行分组?我的意思是,有没有办法说“如果这个变量是某个值,运行这组测试。如果这个变量是一些其他变量,运行这组测试”?

需要它的基本示例(显然,它实际上不起作用,但应该向您展示我想要的东西)。假设要测试的用户在别处定义并且当前正在测试的用户是@user。尽管您可能有更好的替代方案,但这很好。

before do 
  login_as_user(@user) #This logs them in and brings them to the homepage to be tested
  page.visit("/homepage")
end
describe "Check the user homepage"
  subject {page}
  it {should have_content("Welcome, #{@user.name}!")}
  if(@user.role=="admin")
    it {should have_link("List Users"}
  end
end

请记住,我无法控制正在测试的用户 - 例如,我无法即时创建用户,并且不能保证任何给定用户存在,而且我不知道给定用户的角色组合是什么会有。因此,我确实需要某种方式来说明“仅在满足这些条件时才运行此测试”,而不是一种创建可以运行每个测试的情况的方式。

【问题讨论】:

  • 我很好奇它的实际用例是什么。
  • 我必须为几个权限设置相当复杂的用户编写一些断言测试。最常见的情况是我想检查用户属性以查看他们是否有权查看给定页面 - 如果有,我想运行标准测试,如果他们没有,我想确保他们获得他们正在访问的页面的权限被拒绝页面。需要检查具有各种权限(和权限继承)的各种用户。
  • 是否有特殊原因,您不能针对不同的测试环境使用单独的 describe/context 块,然后在每个上下文中在 before 中模拟/存根用户的权限?
  • 因为我在实际页面上进行验收测试(通过 capybara),所以 mock 不起作用,因为它不是有效的会话数据。除非你的意思不是我认为你的意思。你知道吗,我会在那里抛出一个基本的用例,如果你认为有一种方法可以用描述和存根重写它,请随意 - 如果它有效,我愿意接受。
  • 我发现条件逻辑在循环测试时确实有效 - 例如,您可以在此页面上执行类似操作:github.com/rspec/rspec-core/issues/470 但是,这是一个范围问题 - @user 不存在就逻辑而言。嗯...

标签: ruby testing rspec


【解决方案1】:

您可以使用let(或者可能是let!)来定义登录用户的身份。 (显然用适当的工厂/夹具/等替换@regular_user & @admin_user。)

before do
  login_as_user(user)
  page.visit "/homepage"
end
let(:user) { @regular_user }

describe "Check the user homepage" do
  subject { page }
  it { should have_content "Welcome, #{@user.name}!" }

  context "when an administrator" do
    let(:user) { @admin_user }
    it { should have_link "List Users" }
  end
end

【讨论】:

  • 由于我无法访问我正在测试的系统,因此此类事情的工厂/装置是正确的。不幸的是,不能保证给定用户会存在(并且由于无法创建,我仍然需要一种方法来在没有 admin_user 的情况下不运行 admin_user 测试)。这种方法实际上确实有一些我会考虑的有趣用途,但我不完全确定它会解决我的问题。我将在原始问题中说明无法根据需要创建用户。
【解决方案2】:

好吧,显然问题就这么简单:@user 是一个实例变量,它仅在执行测试时存在。因此,动态生成测试不适用于实例变量。

但是,通过在任何测试样式块(之前、之后、it 或指定)之外的某个地方将其声明为局部变量,您可以访问它以用于条件逻辑。

解决方案很简单,只需将 @ 符号从用户面前取下即可。

【讨论】:

    【解决方案3】:

    同样的想法,你可以使用静态变量

    为了方便环境切换,我什至使用了系统全局变量

    在我的 spec_helper.rb 中,我设置了默认设置

    default_env = {
      'SITE_ROOT' => "http://localhost:3000",
      'ACCOUNT_ID' => 'user',
      'ACCOUNT_PASSWORD' => 'password',
      'SUBMIT_REAL_MONEY' => 'false'
    }
    
    # setting default env variables if no ENV ones exists
    default_env.each do |const_name, value|
      val = ENV[const_name].nil? ? value : ENV[const_name]
      eval_str = "#{const_name}='#{val}'"
      puts eval_str
      eval eval_str
    end
    

    然后我可以在调用我的规范的命令行中指定我的设置:

    SITE_ROOT='https://my.production.site/' SUBMIT_REAL_MONEY=true rspec
    

    这是一个简单条件背后的规范:

    if SUBMIT_REAL_MONEY == 'true'
      it { should respond_with 200 }
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 2017-02-11
      • 2014-04-05
      • 2013-07-04
      • 2017-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多