目录结构
规范通常放置在描述其用途的规范目录结构中
模型规范 位于
spec/models
目录中控制器规范 位于
spec/controllers
目录中请求规范 位于
spec/requests
目录中。该目录也可以命名为integration
或api
。功能规范 位于
spec/features
目录中视图规范 位于
spec/views
目录中助手规范 位于
spec/helpers
目录中邮件程序规范 位于
spec/mailers
目录中路由规范 位于
spec/routing
目录中作业规范 位于
spec/jobs
目录中系统规范 位于
spec/system
目录中
应用程序开发人员可以自由地使用不同的目录结构。为了包含正确的 rspec-rails
支持函数,规范需要具有相应的元数据 :type
值
- 模型规范:
type: :model
- 控制器规范:
type: :controller
- 请求规范:
type: :request
- 功能规范:
type: :feature
- 视图规范:
type: :view
- 助手规范:
type: :helper
- 邮件程序规范:
type: :mailer
- 路由规范:
type: :routing
- 作业规范:
type: :job
- 系统规范:
type: :system
例如,假设 ThingsController
的规范位于 spec/legacy/things_controller_spec.rb
中。只需在规范的 RSpec.describe
块中标记 type: :controller
元数据即可
# spec/legacy/things_controller_spec.rb
RSpec.describe ThingsController, type: :controller do
describe "GET index" do
# Examples
end
end
注意:默认情况下,标准 RSpec 规范不需要任何其他元数据。
查看 rspec-core
文档上的 使用元数据 以获取更多详细信息。
自动添加元数据
3.0.0 之前的 RSpec 版本会根据规范在文件系统中的位置自动添加元数据。这对新用户来说既令人困惑,对一些资深用户来说也不理想。
必须明确启用此行为
# spec/rails_helper.rb
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
end
由于这种假设的行为在教程中非常普遍,rails generate rspec:install
生成的默认配置启用了此行为。
如果您遵循上述列出的规范目录结构并已配置 infer_spec_type_from_file_location!
,RSpec 将自动包含每个类型的正确支持函数。
如果您想为不符合上述规范结构的自定义目录设置元数据,可以执行以下操作
# set `:type` for serializers directory
RSpec.configure do |config|
config.define_derived_metadata(:file_path => Regexp.new('/spec/serializers/')) do |metadata|
metadata[:type] = :serializer
end
end
关于规范位置的提示
建议 spec/
目录结构大体上镜像 app/
和 lib/
。这样可以轻松找到相应的代码和规范文件。
示例
app
├── controllers
│ ├── application_controller.rb
│ └── books_controller.rb
├── helpers
│ ├── application_helper.rb
│ └── books_helper.rb
├── models
│ ├── author.rb
│ └── book.rb
└── views
├── books
└── layouts
lib
├── country_map.rb
├── development_mail_interceptor.rb
├── environment_mail_interceptor.rb
└── tasks
└── irc.rake
spec
├── controllers
│ └── books_controller_spec.rb
├── country_map_spec.rb
├── features
│ └── tracking_book_delivery_spec.rb
├── helpers
│ └── books_helper_spec.rb
├── models
│ ├── author_spec.rb
│ └── book_spec.rb
├── rails_helper.rb
├── requests
│ └── books_spec.rb
├── routing
│ └── books_routing_spec.rb
├── spec_helper.rb
├── tasks
│ └── irc_spec.rb
└── views
└── books
标准 Rails 规范必须指定 :type
元数据
给定一个名为“spec/functional/widgets_controller_spec.rb”的文件,其中包含
require "rails_helper"
RSpec.describe WidgetsController, type: :controller do
it "responds successfully" do
get :index
expect(response.status).to eq(200)
end
end
当我运行 rspec spec
那么该示例应该通过。
与 Rails 无关的规范默认情况下不需要 :type
元数据
给定一个名为“spec/ledger/entry_spec.rb”的文件,其中包含
require "spec_helper"
Entry = Struct.new(:description, :us_cents)
RSpec.describe Entry do
it "has a description" do
is_expected.to respond_to(:description)
end
end
当我运行 rspec spec
那么该示例应该通过。
从文件位置推断规范类型会添加相应的元数据
给定一个名为“spec/controllers/widgets_controller_spec.rb”的文件,其中包含
require "rails_helper"
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
end
RSpec.describe WidgetsController do
it "responds successfully" do
get :index
expect(response.status).to eq(200)
end
end
当我运行 rspec spec
那么该示例应该通过。
规范目录中的规范可以覆盖其推断的类型
给定一个名为“spec/routing/duckduck_routing_spec.rb”的文件,其中包含
require "rails_helper"
Rails.application.routes.draw do
get "/example" => redirect("http://example.com")
end
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
end
# Due to limitations in the Rails routing test framework, routes that
# perform redirects must actually be tested via request specs
RSpec.describe "/example", type: :request do
it "redirects to example.com" do
get "/example"
expect(response).to redirect_to("http://example.com")
end
end
当我运行 rspec spec
那么该示例应该通过。