我应该编写哪些测试来测试仅限管理员功能的用户验证?

时间:2016-02-09 01:19:18

标签: ruby-on-rails ruby unit-testing rspec rspec-rails

我创建了一个RSpec规范来测试POST #create操作是否正常工作:

let vc = ViewController() //change this to your class name
self.presentViewController(vc, animated: true, completion: nil)

以上代码正常运行。当我创建另一个测试以仅允许角色为“admin”的用户时,会出现此问题。我是否需要创建新用户,登录,然后运行上述测试?我是否需要为将来根据用户角色进行限制的所有测试执行此操作?

还有其他方法可以进行此类测试吗? 1)只测试create方法是否有效,2)只允许具有“admin”角色的用户访问GET #new和POST #create方法?

2 个答案:

答案 0 :(得分:1)

当您的功能完全开发后,您将要进行以下测试:

  • 一个管理员创造职业生涯的快乐路径测试
  • 一个非管理员试图创造职业但却无法这样做的人
  • 可能是另一个未登录用户尝试创建职业但却无法这样做的人(无论你是否想要这取决于你是否必须编写不同的代码来处理未登录和登录非管理员用户)和
  • 可能是管理员创造职业的不同场景的其他测试。

这种完整,快乐路径测试的想法是测试中最基本的模式之一,但我不知道它有一个名称,除了被术语“快乐”暗示之外路径"

看起来你正在做TDD。大!要从现在的位置到上面的测试列表,下一个要编写的测试是阻止未登录用户创建职业的测试。要使两个测试同时通过,您需要更改第一个测试以登录管理员。如果您需要更多成功创建职业的测试(项目符号4),是的,您还需要在这些项目中登录管理员。

附注:

  • 除非您已经拥有它,否则我不会将您的快乐路径规范写为控制器规范,而是作为功能规范(验收测试)编写,以便您指定UI的重要部分和集成 - 测试整个堆栈。您的失败身份验证规范可能可用作控制器规范,但您可能决定在用户​​至少对其中一个方案没有权限时接受测试用户界面。

  • 我真的不喜欢expect {}.to change语法。它会阻止您对发布结果做出任何其他期望。在您的示例中,我希望HTTP响应状态为200(response.should be_success)。正如我所说,我的第一个规格是功能规格,而不是控制器规格。

答案 1 :(得分:0)

所以,这是一个有趣的问题。是的,您绝对应该(IMO)测试身份验证与目标方法/操作分开。这些中的每一个都构成一个功能单元,应该进行测试。

在我目前的项目中,我赞成PORO(我经常把它们放在一个名为“管理员”的目录中,虽然我知道很多人都喜欢称他们为“服务”#);对于各种各样的事情,因为它让我隔离功能并独立测试它。所以,我最终会得到类似的东西:

# controllers/foo_controller.rb
class FooController < ApplicationController
  before_action :authenticate

  def create
    @results = FooManager.create(params)
    redirect_to (@results[:success] ? my_happy_path : my_sad_path)
  end

  def authenticate
    redirect_to unauthorized_path unless AuthenticationManager.authenticate(params, request)
  end
end

# managers/foo_manager.rb
class FooManager
  class << self

    def create(params)
      # do a bunch of great stuff and return a hash (perhaps a 
      # HashWithIndifferentAccess, if you like) which will 
      # allow for evaluation of @results[:success] back in the
      # controller.
    end

  end
end

# managers/authentication_manager.rb
class AuthenticationManager
  class << self

    def authenticate(params, request)
      # do a bunch of great stuff and return a boolean
    end

  end
end

通过这样的方法,我可以非常轻松地独立测试FooManager.createAuthenticationManager.authenticate(以及FooController.createFooController.authenticate路由)。万岁!

现在,无论您的身份验证框架或控制器方法在单元级别上是否正常运行,正如Dave指出的那样,这是一个单独的问题,而不是整个系统是否按预期运行。我和他一起进行高级集成测试,这样你就可以清楚地知道做了什么&#39;看起来像你知道什么时候发送它!&#39;