Nodejs學習筆記之測試驅動,nodejs學習筆記測試

來源:互聯網
上載者:User

Nodejs學習筆記之測試驅動,nodejs學習筆記測試

分享第二章,關於測試驅動。這裡的測試主要針對Web後端的測試 —— 你為什麼要寫測試案例(即測試案例的完善是否是浪費時間),如何完善你的測試案例,代碼設計如何簡化測試案例的書寫,以及一些後期的構想。

1. 你為什麼要寫測試案例

這個習慣通常會被認為是一種耽誤開發進度的行為,你需要花費幾乎和開發代碼相同的時間來逐步完善你的測試案例。但是在開發過程中,在開發完成一段代碼後如果負責任而不是說完全把問題交給測試人員去發現的話,這個時候通常都會去做一些手動的測試。例如:

在代碼中執行某些方法,查看輸出的值是否符合預期。
修改資料庫/緩衝,然後執行某些方法,看資料庫的變化是否符合預期。
使用工具類比請求某些介面,查看介面的傳回值/資料庫的變化值是否會符合預期。
如果有前端頁面的話,還會涉及到前後端聯調,即要在前端頁面上通過前端互動,查看前端的反饋是否符合預期,來間接驗證後端代碼的正確性。
現代化的測試載入器都在儘可能的將這些人工的手動測試行為抽象成代碼塊,當你有意識去進行手動測試的時候,其實已經開始在嘗試測試案例的行為了。既然可以通過手動的方式進行測試,那為什麼還需要用代碼來實現測試?

代碼是可以複用或者在簡單重構後可以實現更多的功能的,但是當你選擇手動的時候,每次你都需要重頭開始。
成熟的工作流程中應當包括代碼審核流程,代碼審核的方式有很多,逐句閱讀你的代碼,或者檢查你測試代碼的完善性以及正確性,然後運行你的測試案例。後者更加簡單。
當代碼改動,例如修複 Bug 時候,很難保證你的改動是否會影響其他依賴你代碼的部分。在人工測試的時代有一個叫做迴歸測試,即在你修複 Bug 將你的系統重新測試一遍。但是如果你已經有了完善的測試案例了呢,直接執行命令搞定。
當你重構代碼的時候,同上。

2. 如何完善你的測試案例

在進入完善階段前,先說說你將如何?測試案例。

describe Meme do before do  @meme = Meme.new end describe "when asked about cheeseburgers" do  it "must respond positively" do   @meme.i_can_has_cheezburger?.must_equal "OHAI!"  end end describe "when asked about blending possibilities" do  it "won't say no" do   @meme.will_it_blend?.wont_match /^no/i  end endend

上面的代碼來自於 Ruby 的 minitest。before 包含的代碼塊是在執行下面的測試案例前要做的事情,通常還會支援一個相對應的方法,在測試案例執行完執行。每個用例裡面都進行一些很小的判斷。

第一段中提到了一些手動測試裡面經常會涉及到的測試內容,這裡拿其中的 2 和 3 進行說明。在進行資料庫相關的測試時,需要在 before 中插入一條測試資料,並且在 after 中刪除測試資料。中間的測試案例中,通過執行相應的方法,執行完畢後:檢查資料變化情況/檢查是否有預期的異常/是否返回預期結果 來確認代碼的正確性。如果是介面的話,就是通過代碼發起對應的請求,然後檢查返回的內容是否返回預期,有需要的話再去查看資料庫裡面的資料是否符合預期變化。

現在已經有了測試案例,但是任然需要考慮一種特殊情況。我現在為一個函數寫了相對完善的測試案例了,跑完都 PASS 了,結果發現線上的日誌裡面還是有那個函數的報錯。檢查下發現函數的某個分支之前在測試的時候沒有測試到,剛好線上的某種情況運行到了這個分支,結果有一個很不明顯的語法錯誤報錯了,有沒有辦法能確保所有的代碼都測試過了?這裡需要引入的是一個叫做 測試案例覆蓋率 的概念,基本上每個語言都會有響應的實現。通過測試案例覆蓋率,量化的告訴你你的測試案例有沒有跑完某某檔案裡的所有代碼,而你需要做的,就是儘可能保證你的覆蓋率保持在 100%。

某種意義上來說,測試案例和測試覆蓋率是用來提高開發人員對自己代碼自信心的工具。但是,他們也不是萬能的。測試案例裡面總可能會漏掉一些參數的可能性,當然你的代碼裡面也沒有為這種可能性進行代碼的編寫,最終測試案例覆蓋率只能告訴你你寫的代碼我們都幫你檢測過了測試過了,對於你沒有考慮到的可能性,表示無能為力。所以儘可能編寫嚴格的代碼,例如 javascript 裡面儘可能都用 === 而不是 ==,使用強型別的編程規範等等,這些來降低這種因為接受的參數範圍過大帶來的潛在風險。

3. 代碼設計如何簡化測試案例的書寫

整個 Web (也不局限於 web)通常包括三個層面的代碼 —— 單純資料處理與運算、涉及到資料庫、涉及到具體的網路通訊協定。其中單純的資料運算於處理主要為普通的運算的函數或者是其他代碼,涉及到資料庫就是傳統意義上 MVC 裡面的 M,涉及到具體的網路通訊協定就是對應的 C。這三塊的測試分別對應著第一節中常規的測試內容的前三條。

因為 C層面通常還可能涉及到頁面的渲染以及相應協議的類比,所以通常把測試的重心放在函數以及資料庫相關的代碼裡面可以減少測試案例代碼的複雜度,這個就要求 Controller 的代碼要儘可能少。對於複雜度較高的應用的一些目前的一些建議:

將資料的基礎校正都放在 M層,如果使用 Ruby 開發的話,ActiveRecord以及Mongoid都提供了很方便使用的 validation 功能。
嘗試在代碼中使用 Pub/Sub 模式配合一些 ORM中提供的鉤子(hook) 來實現 Model 之間的通訊。 例如在 A 建立的時候發布某個訊息,B監聽到訊息之後修改他自己的某個屬性值。
使用 Command 模式將一些業務無關的功能從系統中抽離出來,例如郵件發送。
以上建議參考:Laravel wisper resque

4. 構想

以上的內容都避開了前後端需要聯調的測試案例,下面的內容主要是針對這塊。Ruby 在這個方向已經有一些比較優雅的實現,感興趣的可以直接先去欣賞一下 Capybara。

隨著包括 Selenium Phantomjs 以及基於前者的 Watir 等一系列瀏覽器驅動的普及,使用代碼控制瀏覽器已經不再是一件很複雜的事情。在這個能力的基礎上,可以嘗試把基於前端的測試分為四步:

等待某標誌性元素出現(例如等待頁面載入玩,或者某個內容非同步載入出現)
類比使用者操作,這裡的操作包括且不局限於使用者點擊、使用者輸入
等待反饋中標誌性元素出現(例如某某輸入框出現)
判斷內容,是否符合預期
基於這個流程,可以解決絕大多數的前端測試。但是單純依靠這個流程任然不夠,因為頁面中可能出現例如驗證碼這樣的阻礙元素,在不修改代碼的前提下,可以嘗試通過資料庫/緩衝來取到這些內容。同樣,和測試介面相同,這裡也涉及到在測試前資料庫中插入測試資料,測試案例執行後嚴重資料庫裡面資料變化,以及全部測試完畢後刪除測試資料的內容。最終導致這塊測試案例代碼的實現需要同時對前端後端有一定的瞭解。目前還在考慮在借鑒 Capybara 的基礎上,設計出更加通用的方案。

最後貼一段 Capybara 的代碼結束這段內容:

feature "Signing in" do background do  User.make(:email => 'user@example.com', :password => 'caplin') end scenario "Signing in with correct credentials" do  visit '/sessions/new'  within("#session") do   fill_in 'Email', :with => 'user@example.com'   fill_in 'Password', :with => 'caplin'  end  click_button 'Sign in'  expect(page).to have_content 'Success' end given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') } scenario "Signing in as another user" do  visit '/sessions/new'  within("#session") do   fill_in 'Email', :with => other_user.email   fill_in 'Password', :with => other_user.password  end  click_button 'Sign in'  expect(page).to have_content 'Invalid email or password' endend

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.