ディレクトリ構造
仕様は通常、目的を説明するための標準的なディレクトリ構造に配置されます。
-
モデルの仕様 は
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
のドキュメントの メタデータの使用方法 を参照してください。
メタデータの自動追加
RSpecのバージョン3.0.0より前では、ファイルシステム上の場所に基づいてスペックにメタデータが自動的に追加されました。これは新規ユーザーにとって混乱を招き、一部のベテランユーザーにとっては望ましくありませんでした。
この動作を明示的に有効にする必要があります。
(# 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 ├── enviroment_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
メタデータを指定する必要があります
Given a file named "spec/functional/widgets_controller_spec.rb" with:
require "rails_helper"
RSpec.describe WidgetsController, type: :controller do
it "responds successfully" do
get :index
expect(response.status).to eq(200)
end
end
When I run rspec spec
Then the example should pass.
非Rails関連のスペックは、デフォルトでは:type
メタデータを必要としません
Given a file named "spec/ledger/entry_spec.rb" with:
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
When I run rspec spec
Then the example should pass.
ファイルの場所からスペックのタイプを推測し、適切なメタデータを追加します
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
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
When I run rspec spec
Then the example should pass.
カノニカルディレクトリ内のスペックは、推測されたタイプを上書きできます
Given a file named "spec/routing/duckduck_routing_spec.rb" with:
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
When I run rspec spec
Then the example should pass.