使用 PageObjects 讓 Integration Test 更好維護

先看看現在的 Home feature spec:

require "rails_helper"

RSpec.describe "Home" do
  scenario "welcomes user" do
    visit root_url

    expect(page).to have_text "Welcome"
  end

  scenario "has navbar element" do
    visit root_url

    expect(page).to have_css "nav.navbar"
  end
end

這樣的測試已經非常好了,但要是可以有代表 Home Page 的對象那就更好了。

之後再別的測試中,我們也可以重複使用這個代表 Home Page 的對象,來重複訪問首頁。

讓我們來實現 PageObjects 吧,首先將我們的測試改寫為:

require "rails_helper"

RSpec.describe "Home" do
  scenario "welcomes user" do
    home_page.go

    expect(page).to have_text "Welcome"
  end

  scenario "has navbar element" do
    home_page.go

    expect(page).to have_css "nav.navbar"
  end

  def home_page
    PageObjects::Pages::Home.new
  end
end

錯誤訊息

$ rspec spec/features/home_spec.rb
FF

Failures:

 1) Home welcomes user
    Failure/Error: PageObjects::Pages::Home.new

    NameError:
      uninitialized constant PageObjects

 2) Home has navbar element
    Failure/Error: PageObjects::Pages::Home.new

    NameError:
      uninitialized constant PageObjects

Finished in 0.00835 seconds (files took 2.1 seconds to load)
2 examples, 2 failures

沒有 uninitialized constant PageObjects,新增:

mkdir -p spec/support/page_objects/pages/
touch spec/support/page_objects/pages/base.rb

spec/support/page_objects/pages/base.rb 填入:

module PageObjects
  class Base
    include Capybara::DSL
    include Rails.application.routes.url_helpers
  end
end

這個 PageObjects::Base 類別放所有 PageObjects 子類共用的方法:

  • include Capybara::DSL

    可以用所有 Capybara 提供的 DSL。

  • include Rails.application.routes.url_helpers

    可以用所有 Rails 提供的 routing helper。

建立 Home Page 的 Page Object:

touch spec/support/page_objects/pages/home.rb

填入:

require_relative "base"

module PageObjects
  module Pages
    class Home < Base
      def go
        visit root_url
      end
    end
  end
end

在對象裡操作 routing helper 需要給環境加上 Host 信息:

修改 config/environments/test.rb

diff --git a/config/environments/test.rb b/config/environments/test.rb
index 30587ef..e3b6a51 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -39,4 +39,6 @@ Rails.application.configure do

   # Raises error for missing translations
   # config.action_view.raise_on_missing_translations = true
+
+  Rails.application.routes.default_url_options[:host] = "localhost:3000"
 end

所有的改動:

diff --git a/config/environments/test.rb b/config/environments/test.rb
index 30587ef..e3b6a51 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -39,4 +39,6 @@ Rails.application.configure do

   # Raises error for missing translations
   # config.action_view.raise_on_missing_translations = true
+
+  Rails.application.routes.default_url_options[:host] = "localhost:3000"
 end
diff --git a/spec/features/home_spec.rb b/spec/features/home_spec.rb
index a224cdf..e29eeb5 100644
--- a/spec/features/home_spec.rb
+++ b/spec/features/home_spec.rb
@@ -2,14 +2,18 @@ require "rails_helper"

 RSpec.describe "Home" do
   scenario "welcomes user" do
-    visit root_url
+    home_page.go

     expect(page).to have_text "Welcome"
   end

   scenario "has navbar element" do
-    visit root_url
+    home_page.go

     expect(page).to have_css "nav.navbar"
   end
+
+  def home_page
+    PageObjects::Pages::Home.new
+  end
 end
diff --git a/spec/support/page_objects/pages/base.rb b/spec/support/page_objects/pages/base.rb
new file mode 100644
index 0000000..b36da2f
--- /dev/null
+++ b/spec/support/page_objects/pages/base.rb
@@ -0,0 +1,6 @@
+module PageObjects
+  class Base
+    include Capybara::DSL
+    include Rails.application.routes.url_helpers
+  end
+end
diff --git a/spec/support/page_objects/pages/home.rb b/spec/support/page_objects/pages/home.rb
new file mode 100644
index 0000000..386f604
--- /dev/null
+++ b/spec/support/page_objects/pages/home.rb
@@ -0,0 +1,11 @@
+require_relative "base"
+
+module PageObjects
+  module Pages
+    class Home < Base
+      def go
+        visit root_url
+      end
+    end
+  end
+end

重新執行測試,現在測試應該跑通了!

results matching ""

    No results matching ""