RSpec.describe "Hello", type::requestdo describe "GET /"do context "when good_bye_world feature flag is enabled"do before do allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(true) end
it "returns 'good bye world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") end end
context "when good_bye_world feature flag is disabled"do before do allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(false) end
it "returns 'hello world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("hello world") end end
context "when good_bye_world feature flag is not set"do it "returns 'hello world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("hello world") end end end end
実行して、テストが通ることを確認する。
1 2 3 4 5 6 7 8 9 10 11 12 13
$ bundle exec rspec
Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' when good_bye_world feature flag is disabled returns 'hello world' when good_bye_world feature flag is not set returns 'hello world'
Finished in 0.48919 seconds (files took 7.65 seconds to load) 3 examples, 0 failures
Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' (FAILED - 1) when good_bye_world feature flag is disabled returns 'hello world' (FAILED - 2) when good_bye_world feature flag is not set returns 'hello world' (FAILED - 3)
Failures:
1) Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' Failure/Error: allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(true) FeatureFlag(id: integer, is_available: boolean, created_at: datetime, updated_at: datetime, key: string) does not implement: good_bye_world_enabled? # ./spec/requests/hello_spec.rb:7:in `block (4 levels) in <top (required)>'
2) Hello GET / when good_bye_world feature flag is disabled returns 'hello world' Failure/Error: allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(false) FeatureFlag(id: integer, is_available: boolean, created_at: datetime, updated_at: datetime, key: string) does not implement: good_bye_world_enabled? # ./spec/requests/hello_spec.rb:19:in `block (4 levels) in <top (required)>'
3) Hello GET / when good_bye_world feature flag is not set returns 'hello world' Failure/Error: unless(FeatureFlag.good_bye_world_enabled?)
Finished in 0.37588 seconds (files took 8.03 seconds to load) 3 examples, 3 failures
Failed examples:
rspec ./spec/requests/hello_spec.rb:10 # Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' rspec ./spec/requests/hello_spec.rb:22 # Hello GET / when good_bye_world feature flag is disabled returns 'hello world' rspec ./spec/requests/hello_spec.rb:30 # Hello GET / when good_bye_world feature flag is not set returns 'hello world'
RSpec.describe "Hello", type::requestdo describe "GET /"do # 削除 ここではコメントアウト # context "when good_bye_world feature flag is enabled" do # before do # allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(true) # end # # it "returns 'good bye world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("good bye world") # end # end # # context "when good_bye_world feature flag is disabled" do # before do # allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(false) # end # # it "returns 'hello world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("hello world") # end # end
context "when good_bye_world feature flag is not set"do it "returns 'hello world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("hello world") end end end end
RSpec.describe "Hello", type::requestdo describe "GET /"do # 削除 ここではコメントアウト # context "when good_bye_world feature flag is enabled" do # before do # allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(true) # end # # it "returns 'good bye world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("good bye world") # end # end # # context "when good_bye_world feature flag is disabled" do # before do # allow(FeatureFlag).to receive(:good_bye_world_enabled?).and_return(false) # end # # it "returns 'hello world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("hello world") # end # end
context "when good_bye_world feature flag is not set"do it "returns 'good bye world'"do# < -- 修正 get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") # < -- 修正 end end end end
RSpec.describe "Hello", type::requestdo describe "GET /"do # 省略 context "when good_bye_world_enabled is not defined"do it "returns 'good bye world'"do get "/"
# FeatureFlag は、good_bye_world_enabled?メソッドを持っているか? if !FeatureFlag.respond_to?(:good_bye_world_enabled?) expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") else expect(response).to have_http_status(:ok) expect(["hello world", "good bye world"]).to include(response.body) end end end end end
RSpec.describe "Hello", type::requestdo describe "GET /"do context "when good_bye_world feature flag is enabled"do before do allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(true) end
it "returns 'good bye world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") end end
context "when good_bye_world feature flag is disabled"do before do allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(false) end
it "returns 'hello world'"do get "/" expect(response).to have_http_status(:ok) expect(response.body).to eq("hello world") end end
context "when good_bye_world feature flag is not set"do it "returns 'good bye world"do get "/"
ifdefined?(GoodByeWorldFeatureFlag) expect(response).to have_http_status(:ok) expect(["hello world", "good bye world"]).to include(response.body) else expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") end end end end end
こちらもテストは以下のように成功する。
1 2 3 4 5 6 7 8 9 10 11 12 13
$ bundle exec rspec
Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' when good_bye_world feature flag is disabled returns 'hello world' when good_bye_world feature flag is not set returns 'hello world' or 'good bye world Finished in 0.40968 seconds (files took 7.96 seconds to load) 3 examples, 0 failures
Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' (FAILED - 1) when good_bye_world feature flag is disabled returns 'hello world' (FAILED - 2) when good_bye_world feature flag is not set returns 'hello world' or 'good bye world (FAILED - 3) Failures: 1) Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' Failure/Error: allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(true) NameError: uninitialized constant GoodByeWorldFeatureFlag # ./spec/requests/hello_spec.rb:7:in `block (4 levels) in <top (required)>'
2) Hello GET / when good_bye_world feature flag is disabled returns 'hello world' Failure/Error: allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(false)
3) Hello GET / when good_bye_world feature flag is not set returns 'hello world' or 'good bye world Failure/Error: unless GoodByeWorldFeatureFlag.enabled? NameError: uninitialized constant HelloController::GoodByeWorldFeatureFlag # ./app/controllers/hello_controller.rb:3:in `index' # /usr/local/bundle/gems/turbo-rails-2.0.23/lib/turbo-rails.rb:24:in `with_request_id' # /usr/local/bundle/gems/turbo-rails-2.0.23/app/controllers/concerns/turbo/request_id_tracking.rb:10:in `turbo_tracking_request_id' # /usr/local/bundle/gems/actiontext-7.2.3.1/lib/action_text/rendering.rb:25:in `with_renderer' # /usr/local/bundle/gems/actiontext-7.2.3.1/lib/action_text/engine.rb:71:in `block (4 levels) in <class:Engine>' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/tempfile_reaper.rb:20:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/etag.rb:29:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/conditional_get.rb:31:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/head.rb:15:in `call' # /usr/local/bundle/gems/rack-session-2.1.2/lib/rack/session/abstract/id.rb:274:in `context' # /usr/local/bundle/gems/rack-session-2.1.2/lib/rack/session/abstract/id.rb:268:in `call' # /usr/local/bundle/gems/railties-7.2.3.1/lib/rails/rack/logger.rb:41:in `call_app' # /usr/local/bundle/gems/railties-7.2.3.1/lib/rails/rack/logger.rb:29:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/method_override.rb:28:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/runtime.rb:24:in `call' # /usr/local/bundle/gems/rack-3.2.6/lib/rack/sendfile.rb:131:in `call' # /usr/local/bundle/gems/railties-7.2.3.1/lib/rails/engine.rb:535:in `call' # /usr/local/bundle/gems/rack-test-2.2.0/lib/rack/test.rb:360:in `process_request' # /usr/local/bundle/gems/rack-test-2.2.0/lib/rack/test.rb:153:in `request' # ./spec/requests/hello_spec.rb:31:in `block (4 levels) in <top (required)>'
Finished in 0.21992 seconds (files took 7.83 seconds to load) 3 examples, 3 failures
Failed examples:
rspec ./spec/requests/hello_spec.rb:10 # Hello GET / when good_bye_world feature flag is enabled returns 'good bye world' rspec ./spec/requests/hello_spec.rb:22 # Hello GET / when good_bye_world feature flag is disabled returns 'hello world' rspec ./spec/requests/hello_spec.rb:30 # Hello GET / when good_bye_world feature flag is not set returns 'hello world' or 'good bye world
RSpec.describe "Hello", type::requestdo describe "GET /"do # 削除 ここではコメントアウト # context "when good_bye_world feature flag is enabled" do # before do # allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(true) # end # # it "returns 'good bye world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("good bye world") # end # end # # context "when good_bye_world feature flag is disabled" do # before do # allow(GoodByeWorldFeatureFlag).to receive(:enabled?).and_return(false) # end # # it "returns 'hello world'" do # get "/" # expect(response).to have_http_status(:ok) # expect(response.body).to eq("hello world") # end # end
context "when good_bye_world feature flag is not set"do it "returns 'good bye world"do get "/"
ifdefined?(GoodByeWorldFeatureFlag) expect(response).to have_http_status(:ok) expect(["hello world", "good bye world"]).to include(response.body) else expect(response).to have_http_status(:ok) expect(response.body).to eq("good bye world") end end end end end
以下のようにテストが通ることを確認する。
1 2 3 4 5 6 7 8 9
$ bundle exec rspec
Hello GET / when good_bye_world feature flag is not set returns 'hello world' or 'good bye world Finished in 0.22334 seconds (files took 8 seconds to load) 1 example, 0 failures
クラスレベルでのフィーチャーフラグの設置から削除まで実行した。
というわけで、『脳に収まるコードの書き方 - 複雑さを避け持続可能にするための経験則とテクニック』のフィーチャーフラグの方針をRuby on Railsで実装してみた。