Rspec中的条件测试?

4
有没有一种方法可以使用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

请记住,我无法控制被测试的用户 - 例如,我无法即时创建用户,也不能保证存在给定的用户,并且我不知道每个用户将具有哪些角色组合。因此,我需要一些方法来表达“只有满足这些条件才运行此测试”的方式,而不是创造每个测试都可以运行的情况。


我很好奇这个的实际用途是什么。 - Andrew Marshall
我需要为几个具有相当复杂权限设置的用户编写一些断言测试。最常见的情况是,我想检查用户属性,以查看他们是否有权限查看给定页面 - 如果有,我希望运行标准测试;如果没有,我希望确保他们得到正确的拒绝访问页面,以便访问他们正在访问的页面。需要检查各种具有各种权限(和权限继承)的用户。 - GlyphGryph
你有没有特别的原因不能为不同的测试情境设置单独的 describe/context 块,然后在每个上下文中使用 before 模拟/存根用户权限? - Andrew Marshall
由于我正在通过capybara对实际页面进行验收测试,所以模拟将不起作用,因为它不是有效的会话数据。除非你的意思与我想的不同。你知道吗,我会放一个基本用例在那里,如果你认为有一种重写它的方法,可以使用描述和存根,请随意 - 如果它能够工作,我很乐意尝试。 - GlyphGryph
我发现条件逻辑在循环测试中确实有效 - 例如你可以像这个页面上所示做的那样:https://github.com/rspec/rspec-core/issues/470 不过,这是一个作用域问题 - 对于逻辑来说,@user并不存在。嗯... - GlyphGryph
http://www.idolhands.com/ruby-on-rails/specs-and-testing/dry-your-tests-with-dynamic-specs-in-rspec 似乎有一些我想要做的东西的好信息。 - GlyphGryph
3个回答

2
你可以使用 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测试)。这种方法实际上确实有一些有趣的用途,我会考虑一下,但我不完全确定它是否能解决我的问题。我将在原始问题中注明无法根据需要创建用户的情况。 - GlyphGryph

2

好的,显然问题很简单:@user是一个实例变量,只有在执行测试时才存在。由于这个原因,动态生成测试无法使用实例变量。

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

解决方案就是将用户前面的@符号去掉,非常简单。


0

在相同的思路下,您可以使用静态变量

为了方便地在不同环境之间切换,我甚至使用系统全局变量

在我的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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接