Website logo

Robert Chang

技術部落格

RSpec - 介紹 Capybara 以及如何設定

在建立一個全新的 Rails 專案時,會在 Gemfile 裡面看到預設的測試套件,分別是:capybara & selenium-webdriver & webdrivers

後面兩個從名字上就可以很明顯的感受到,有種要操縱網頁的概念,而事實也是如此!

Capybara 本身就是模仿一個真實使用者來測試你的應用程式,所以我們會需要有 selenium 這樣的工具來幫助我們自動化的啟動瀏覽器。

有點像我們撰寫程式語言,來操控一個虛擬的人物和瀏覽器互動的概念!

基於 Rails 專案本身就有安裝 capybara 了,我們就會直接用 RSpec 的視角來講一下這個東西該怎麼使用。

Capybara 的優點

為什麼 Rails 會選擇 Capybara 做為預設的套件呢?

其實我也不清楚,但我自己覺得有幾個還不錯的地方可以分享一下!

1. 不需要特別的 set up

這件事情對於新手來說就很友善,因為可以避免設定一些過度複雜的參數。

那些設定可能都會打斷開發的過程,所以有一個好的套件,讓人即插即用是很讚的一件事!

2. 直觀的 API 像人類的語言

等等示範的程式碼裡面,就會看到很有趣的 capybara API,都是一些超級簡單的英文,非常直觀。

例如:訪問一個網站

visit ( 訪問的 url )

這樣就會模擬一個用戶造訪這個網站,看起來真的非常直覺。

3. 可以無痛切換無頭模式以及實際瀏覽器

一般來說 capybara 會在無頭模式下進行測試網站,而無頭模式的瀏覽器是什麼意思?

無頭瀏覽器就是沒有我們現在使用的這些介面,通常透過 command line 來進行溝通。

而切換瀏覽器模式就是,我們可以在測試的時候讓他彈出瀏覽器的畫面,並且在你面前輸入帳號密碼等等,以便測試!

而 Capybara 可以讓你在這兩者間作切換,但不需要更動你原先的程式碼。

上面是三個我自己覺得很厲害的地方,可能因為 capybara 實在是太實用了,就被 Rails 官方給綁定了。

實際使用

在 RSpec 中,有提到過 Feature test,重要度非常高,就是使用 capybara 來完整整個流程。

那我們要如何在 RSpec 中使用它呢?

只要給他正確的 tag 就可以了。

像這樣:

RSpec.feature 'test something', type: :feature do
 ....
end

使用 RSpec.feature 並加入了 type: :feature / type: :system 就可以使用了喔!

有沒有很符合我提到的優點呢? 基本上真的不太需要什麼特別的設定就可以簡單地使用了!

使用情境

接著會用一些簡單的程式碼讓人可以快速理解 capybara 在做些什麼,以及 feature test 到底在做些什麼呢?

假設我們要針對 登入 這項功能來做 feature test,可以先試想一下整個情境以及流程。

進入登入頁面 > 填寫帳號以及密碼 > 登入成功

這邊先不考慮失敗的情境,因為其實就是多一個登入失敗而已!

先上程式碼再慢慢解說:

RSpec.feature 'Sign In', type: :feature do

  before do
    create(:user)
    # 先讓資料庫有這筆資料
  end

  scenario 'sign in process' do
    visit '/sessions/new'
    within("#session") do
      fill_in 'Email', with: 'user@example.com'
      fill_in 'Password', with: 'password'
    end
    click_button 'Sign in'
    expect(page).to have_content 'Success'
  end
end

這邊的 scenario 等同於之前我們使用的 it, 但語意更明確一些,有點像是創造一個情境的概念。

接著我們看到第 9 行的程式碼,拜訪 /sessions/new 這個網站,但這邊的寫法不太好,其實我們可以用 rails 的 routes prefix 來造訪網站喔!

visit new_user_session # users/sessions#new

而看到第 10 行 within('#session') 是找到這個表格,而 #session 這就是我們熟悉的 CSS 選擇器找 ID 的用法。

進入表格後呢,找到 Email 以及 Password 這兩個欄位並且填入事先創建好的 User 帳號密碼!

在到 第 14 行,按下登入按鈕,並且期待頁面會有 Success 的文字出現!

這樣算是完成了一個簡易的 feature test,這邊的示範也呼應了我提到的第二個優點,Capybara 讓呼叫 API 的過程變得流暢和舒服!

所以這次的測試流程是:

# 拜訪登入網站 > 找到登入的表格 > 填寫帳號密碼 > 按下登入按鈕 > 期待看到成功訊息!

因為是自動化的測試程序,所以機器其實比我們想像的還要笨,我們需要給予它很瑣碎的指令,可以往上看到,以我們人類來說想像的測試流程會太過於簡單。

是因為人類的腦袋幫助我們節省了很多習以為常的事情,但對於寫程式來說,這些都是要考慮進去的喔!

常見問題

1. 我想看到瀏覽器彈出來的樣子!

我們只需要在 spec_helper.rb 裡面加入:

Capybara.javascript_driver = :selenium_chrome

就會在執行 feature test 的時候,從無頭模式切換到瀏覽器模式喔!

第一次看到的時候真的覺得超酷的,因為它會自動的填寫帳號密碼等等,像一個真實的使用者!

2. 為什麼我的頁面找不到按鈕了?

常常會遇到在 click_button 的時候找不到按鈕的情形。

最常遇到的有三種可能:

第一種:你的按鈕是跟隨著資料出現的,例如:編輯這顆按鈕,在你沒有資料的情境下,畫面上就真的沒有,所以要記得在 before do 的時候先建立好相關的資料,讓測試的情境更寫實喔!

第二種:你的按鈕在 mobile 的情形下會消失,有些專案可能會需要在 mobile 的情境時 hidden 某些按鈕,那就會造成 capybara 找不到它,所以我們也可以設定在測試時的視窗大小喔!

一樣在 spec_helper.rb 加入:

config.before(:each, js: true) do
  Capybara.page.current_window.resize_to(1080, 1920)
end

這樣在每次測試前,都會以這樣的視窗大小進行測試。

第三種:你的按鈕是伴隨著事件出現的,例如你點了某個按鈕後,會利用 Ajax 到後端並且 render 出新的按鈕,但對於 capybara 來說,一切都太快了,他還沒等到按鈕出現,就已經在 click 了,自然而然就找不到。

所以我們也可以在 spec_helper.rb 加入:

Capybara.default_max_wait_time = 5

其實原先的 default 是兩秒,但我們可以提高秒數,來試試看會不會通過測試!

3. 怎麼找我要的元素?

capybara 有提供 css selector 以及 xpath 兩種方式來找到網頁上的元素,當你找不到的時候,可以檢查是不是資料在測試前寫入的順序不對,或是關聯沒建立好等等。

結語

今天的 capybara 就介紹到這邊,關於他的使用方法實在是太多了,在官方文件都有詳細的說明,各個方法要如何使用。

但大部分都脫離不了以使用者角度出發的,拜訪網站、點擊按鈕、填寫等等

也有一些有趣的小功能,說不定會在你需要的時候用到喔!

上一篇文章RSpec - 介紹 FactoryBot Rails 以及如何設定

下一篇文章RSpec - 介紹 WebMock、VCR