gpt4 book ai didi

ruby-on-rails - Rails RSpec,DRY 规范 : shared example vs. 辅助方法与自定义匹配器

转载 作者:数据小太阳 更新时间:2023-10-29 08:35:40 24 4
gpt4 key购买 nike

我对 Controller 规范中的每个 HTTP 方法/ Controller 操作组合重复了一次以下测试:

it "requires authentication" do
get :show, id: project.id
# Unauthenticated users should be redirected to the login page
expect(response).to redirect_to new_user_session_path
end

我找到了以下三种方法来重构它并消除重复。哪个最合适?

共享示例

在我看来,共享示例是最合适的解决方案。但是,必须使用 block 才能将 params 传递给共享示例,感觉有点尴尬。

shared_examples "requires authentication" do |http_method, action|
it "requires authentication" do
process(action, http_method.to_s, params)
expect(response).to redirect_to new_user_session_path
end
end

RSpec.describe ProjectsController, type: :controller do
describe "GET show", :focus do
let(:project) { Project.create(name: "Project Rigpa") }

include_examples "requires authentication", :GET, :show do
let(:params) { {id: project.id} }
end
end
end

辅助方法

这样做的好处是不需要 block 将 project.id 传递给辅助方法。

RSpec.describe ProjectsController, type: :controller do
def require_authentication(http_method, action, params)
process(action, http_method.to_s, params)
expect(response).to redirect_to new_user_session_path
end

describe "GET show", :focus do
let(:project) { Project.create(name: "Project Rigpa") }

it "requires authentication" do
require_authentication(:GET, :show, id: project.id )
end
end
end

自定义匹配器

要是有单行测试就好了。

RSpec::Matchers.define :require_authentication do |http_method, action, params|
match do
process(action, http_method.to_s, params)
expect(response).to redirect_to Rails.application.routes.url_helpers.new_user_session_path
end
end

RSpec.describe ProjectsController, type: :controller do
describe "GET show", :focus do
let(:project) { Project.create(name: "Project Rigpa") }

it { is_expected.to require_authentication(:GET, :show, {id: project.id}) }
end
end

提前致谢。

最佳答案

didroe 在 this Reddit post 中提供的建议让我想到将方法/操作调用 (process) 放在共享代码中并不是一个好主意,因为它增加了复杂性(降低了可读性)并且实际上并没有减少代码重复。

再搜索一些之后,我在 Everyday Rails Testing with RSpec by Aaron Sumner 中找到了我认为最好的选择。书(第 102 页)。

创建以下自定义匹配器:

# spec/support/matchers/require_login.rb
RSpec::Matchers.define :require_login do |expected|
match do |actual|
expect(actual).to redirect_to \
Rails.application.routes.url_helpers.new_user_session_path
end

failure_message do |actual|
"expected to require login to access the method"
end

failure_message_when_negated do |actual|
"expected not to require login to access the method"
end

description do
"redirect to the login form"
end
end

并对每个 Controller 的每个操作使用如下测试:

it "requires authentication" do
get :show, id: project.id
expect(response).to require_login
end

与在所有测试中重复expect(response).to redirect_to new_user_session_path相比,这种方式有以下优点:

  • 改进了可维护性。如果我们最终必须更改此断言,我们会在一个地方更改它,而不必更改数十个或数百个测试。
  • 更好的失败消息。

你怎么看?

关于ruby-on-rails - Rails RSpec,DRY 规范 : shared example vs. 辅助方法与自定义匹配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44597682/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com