摘要:無論合適,優先使用的,而不是。這是一個很有用的工具在測試中用來視圖化。這點非常好,因為我們不想任何測試數據會對別的測試產生副作用。為了遵照的最佳實踐,我們用測試間諜,這樣我們的期待會進入最佳的狀態。下一步這僅僅是個如何開始測試應用的概覽。
我常常被問到,怎樣開始測試 Rails 程序。其實最為一個測試新手,最難得地方在于你不知道一些專業術語或者該問怎樣的問題。下面所寫的是一些概覽,關于我們使用什么工具,為什么使用這些工具,和一些需要牢記在心的建議。
RSpec我們用 RSpec 而不是 Test::Unit,是因為語法更友好,可讀性更高。當然,你可以花幾天時間爭論到底該用哪個框架,每個框架都有自己的優點。最主要的是你在用他們進行測試。
Feature specsFeature specs,可以測試你整個程序的高級測試工具,保證每個部件都工作正常,挺贊的。他是從用戶的角度編寫的,比如用戶點擊或者填寫表單。我們用 RSpec 和 Capybara,他們允許你寫照這樣編寫可以和網頁進行交互的測試。
這是一個 RSpec feature 測試的栗子:
# spec/features/user_creates_a_foobar_spec.rb feature "User creates a foobar" do scenario "they see the foobar on the page" do visit new_foobar_path fill_in "Name", with: "My foobar" click_button "Create Foobar" expect(page).to have_css ".foobar-name", "My foobar" end end
這個測試,模擬了一個用戶打開新建foobar的表單,填入信息,點擊“Create”。這個測試然后假設頁面正如期待,正確地顯示剛才創建的foobar。
這些對于測試高級功能來說很棒,但是記住,feature specs 跑起來很慢。在用 Capybara 測試應用所有的可能路徑的時候,把測試的邊緣情況留模型,視圖,控制器的 sepecs。
我傾向于關于怎么區分 Rspec 和 Capybara 方法的不同點。Capybara 方法實際上是和頁面進行交互,比如點擊,表單操作,或者在頁面上查找元素。你可以在 Capybara 的finders,matchers,和 actions 查看更多文檔。
Model specsModel specs 經常被用來測試系統中較小的部件,比如類或方法,這點和單元測試挺相似的。有時,他們也會和數據庫進行交互。他們運行起來很快,也可以處理正在測試系統(system under test)中的一些邊緣情況。
在 RSpec 中,他們看起來像這樣:
# spec/models/user_spec.rb # Prefix class methods with a "." describe User, ".active" do it "returns only active users" do # setup active_user = create(:user, active: true) non_active_user = create(:user, active: false) # exercise result = User.active # verify expect(result).to eq [active_user] # teardown is handled for you by RSpec end end # Prefix instance methods with a "#" describe User, "#name" do it "returns the concatenated first and last name" do # setup user = build(:user, first_name: "Josh", last_name: "Steiner") # excercise and verify expect(user.name).to eq "Josh Steiner" end end
為了維護的可讀性,確保你寫的測試是 Four Phase Test
?
The Four-Phase Test is a testing pattern, applicable to all programming languages and unit tests (not so much integration tests).
It takes the following general form:
test do setup exercise verify teardown end
比如:
it "encrypts the password" do user = User.new(password: "password") user.save user.encrypted_password.should_not be_nil endController specs
當通過一個控制器測試多個路徑的時候,我們喜歡用 controller specs 而不是 feature specs,因為他很快,而且寫起來容易。
一個好的測試驗證的 use case:
# spec/controllers/sessions_controller_spec.rb describe "POST #create" do context "when password is invalid" do it "renders the page with error" do user = create(:user) post :create, session: { email: user.email, password: "invalid" } expect(response).to render_template(:new) expect(flash[:notice]).to match(/^Email and password do not match/) end end context "when password is valid" do it "sets the user in the session and redirects them to their dashboard" do user = create(:user) post :create, session: { email: user.email, password: user.password } expect(response).to redirect_to "/dashboard" expect(controller.current_user).to eq user end end endView specs
View specs 對于測試在模板中根據條件顯示不同信息來說非常有用,但是很多開發者卻忘了這個,而用 feature specs。然后絞盡腦汁為什么他們花了那么長時間跑測試。當然,你可以用 feature spec 覆蓋每一個條件視圖,但我更喜歡像這樣使用 view specs :
# spec/views/products/_product.html.erb_spec.rb describe "products/_product.html.erb" do context "when the product has a url" do it "displays the url" do assign(:product, build(:product, url: "http://example.com") render expect(rendered).to have_link "Product", href: "http://example.com" end end context "when the product url is nil" do it "displays "None"" do assign(:product, build(:product, url: nil) render expect(rendered).to have_content "None" end end endFactoryGirl
當編寫測試代碼的時候,你會需要在不同場景往數據庫里灌數據。你可以使用內建的User.create,但是當 model 中有很多 validations 時候,這樣好乏味啊。通過User.create,即便你的測試代碼和這些驗證無關,你也不得不指定屬性來滿足 validations。最重要的是,如果后來你修改了 validations,你還要重新修改測試套件的代碼。解決方案就是用 factories(工廠,數據生成器) 或者 fixtures(夾具)來創建模型。
我們更喜歡 factories(和 FactoryGirl)勝過 Rails 的 fixgures,因為 fixtures 是神秘嘉賓。夾具讓人很難看到內因和效果,因為部分邏輯在你使用它的時候已經在文件中被定義好了。因為夾具遠在在測試之前就已經被生成,他們變得很難控制。
Factories,另一方面來說,把邏輯正確地放到測試中。這讓我們很容易地看到正在發生什么,而且對于不同的場景更加靈活。Factories 比夾具更慢,但是從靈活性和可讀性上來說,這點犧牲是值得的!
把數據固化到數據庫也會減慢測試速度。無論合適,優先使用 FactoryGirl 的 build_stubbed,而不是create。build_stubbed 會在內存中生成,避免寫入磁盤。如果你測試一些查詢操作(User.where(admin: true)),你會希望從數據庫里進行查找,這就意味著你必須使用create。
跑帶有 JavaScript 的 specs你會最終碰到一種場景,你需要測試一些依賴 JavaScript 代碼的功能。用默認的驅動跑 specs 不會執行頁面中任何 JavaScript 代碼。
你需要兩個法器,來跑帶有 JavaScript 代碼的功能 specs
安裝一個 JavaScript 驅動
有兩種類型的 JavaScript 驅動。比如像 Selenium,它會打開一個 GUI 窗口瀏覽器,然后在你看著它的時候,在頁面上點擊。這是一個很有用的工具在測試中用來視圖化。但是不幸的是,啟動一整個 GUI 窗口瀏覽器很慢。由于這個原因,我們傾向于使用 headless 瀏覽器。對于 Rails 來說,你可能會使用 Poltergeist 或者 [Capybara] Webkit(https://github.com/thoughtbot/capybara-webkit)。
對于特定的測試使用 JavaScript 元數據關鍵字
feature "User creates a foobar" do scenario "they see the foobar on the page", js: true do ... end end
用合適的關鍵字,RSpec 會根據需要運行任何 JavaScript。
清理數據庫默認情況下,跑 Rails 測試的時候,Rails 會把每個場景都存在數據庫事務中。這就說明,在每個測試結束的時候,Rails 會回滾所有在測試中的修改。這點非常好,因為我們不想任何測試數據會對別的測試產生副作用。
不幸的是,當我們使用 JavaScript 驅動的時候,這個測試實在另一個線程進行的。這就意味著,它并沒有和程序共用同一個數據庫連接,而且為了運行程序看到測試結果,你的測試會提交這個事務。為了解決這個問題,我們可以允許數據庫提交這些數據,然后接著,在每個 spec 后 Truncate 數據庫。這樣會比事務慢一點,所以,我們只在需要的時候使用 truncation。
這就是 Database Cleaner 的用處。Database Cleaner 允許你配置策略。我建議閱讀下 Avdi 的文章 看看血淋淋的細節。這是個極(喪)其(心)詳(病)細(狂)的配置過程,所以我通常在項目中來回拷貝這個文件,或者使用 Suspenders,這樣就可以輕易搞定了。
doubles 和 stubs 方法double 方法可以模擬系統中另外一個對象。經常的,你會需要一個替身,并且只測試一個屬性,所以不值得加載整個 ActiveRecord 對象。
car = double(:car)
當你使用 stubs,你是在告訴一個對象去響應一個已給出的方法。如果 stub 之前的 double
car.stub(:max_speed).and_return(120)
我們現在可以期待當訪問 max_speed 我們的 car 對象總是返回120。臨時產生可以響應一個方法的對象而且帶有同樣的依賴關系,而不用系統中真的存在的對象,這是很棒的方法!在這個栗子中,我們在一個 double 出來的對象上進行了 stub,實際上你還可以在別的對象 stub 任何方法。
我們可以把上邊的代碼簡化為這樣:
car = double(:car, max_spped: 120)
測試間諜(Test Spies)當測試你的程序時,你會碰到你想驗證當一個對象接收到一個指定的方法的場景。為了遵照 Four Phase Test 的最佳實踐,我們用測試間諜,這樣我們的期待會進入最佳的 verify 狀態。之前,我們用 Bourne 做到這點,但是 RSpec 已經在 RSpec Mocks 中包括了這項功能。看看文檔中的這個栗子:
invitation = double("invitation", accept: true) user.accept_invitation(invitation) expect(invitation).to have_received(:accept)用 Webmock stub 外部請求
基于三方服務的測試套件跑起來很慢的,會因為網絡連接的斷開導致失敗,而且也可能會因為服務頻率限制或者缺少沙盒環境導致失敗。
確保你的測試套件在用 Webmock stub 外部請求的時候,不會和三方服務交互。這個可以配置在 spec/spec_helper.rb :
require "webmock/rspec" WebMock.disable_net_connect!(allow_localhost: true)
避免使用三方請求,學習怎樣 stub 外部服務請求。
下一步這僅僅是個如何開始測試 Rails 應用的概覽。為了促進學習,我非常推薦你上我們的 TDD workshop,在這里,你可以通過從零開始建立兩個 Rails 應用,來深度學這些課程。課程覆蓋到重構,為確保應用和測試代碼的可維護性。TDDworkshop 的學生也可以介入我們的工作時間,你實時地可以問我們攻城獅任何問題。
當我是新手的時候我學習了這個課程,我墻裂推薦!
source: http://www.tuicool.com/articles/JrQzyi
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/8681.html
摘要:框架本身可以很好地支持自下而上的單元測試。在中,這些原因可以分為性能真實的操作,依靠定時行為及網絡活動減慢了測試隔離單元測試應把重點放在小的一塊功能成為可能,并解耦不可靠的或低依賴使用對象是擁抱和的基本組成部分。 最近在慢慢深入Backbone,也試著寫一些測試,找一些合適的文檔來學習。于是就找到了一個系列的文章 : Testing Backbone applications with...
摘要:今天小數給大家帶來的是一篇代碼級干貨文章,與大家分享一些利用以微服務形式設置應用的經驗與心得。為何選擇加在我效力的企業中,我們一直在利用為全部工程師構建開發環境。運行命令,從而利用構建鏡像并安裝。 今天小數給大家帶來的是一篇代碼級干貨文章,與大家分享一些利用Rails API以微服務形式設置應用的經驗與心得。 為何選擇Docker加Rails API? 在我效力的企業中,我們一直在利用...
摘要:然而,這些模板并不限制你自己對于使用的架構組織和選擇類庫。目前可用的模板包括全功能的,包括熱加載,靜態檢測,單元測試一個簡易的,以便于快速開始。 最近, 尤大在和人對噴的時候,悄然放出了一個大招,于是為了追趕他的步伐,趕緊試驗了下,并且把原文給大家翻譯下。 原文地址:Announcing vue-cli 譯文源地址: Vuejs自己的構建工具 先上原文翻譯: 最近有很多大量關于Reac...
摘要:今天,就為開發者介紹個方便的工具。對開發者來說,是一個非常有用的工具,它提供了超過個有用的函數。該工具檢查輸入源代碼和報告任何違反給定的標準。框架是一個開發的工具。它側重于安全性和性能,絕對是最安全的開發框架之一。 PHP是為Web開發設計的服務器腳本語言,但也是一種通用的編程語言。超過2.4億個索引域使用PHP,包括很多重要的網站,例如Facebook、Digg和WordPress。...
摘要:首先安裝單元測試環境使用模塊來模擬定義的模型。根據刪除這是單元測試的最后一小節。需要根據需求和單元測試用例來編寫應用邏輯,使我們的程序更加穩定。我們會運行自動測試用例,一直重構,直到所有單元測試都通過。 本文轉載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/746原文:https://semaphoreci.com/community/tutoria...
閱讀 1651·2021-08-13 15:03
閱讀 2082·2019-08-30 15:54
閱讀 3543·2019-08-26 10:30
閱讀 1019·2019-08-26 10:22
閱讀 2745·2019-08-23 14:42
閱讀 1808·2019-08-22 11:16
閱讀 1037·2019-08-21 18:33
閱讀 3159·2019-08-21 17:28