文檔即測試?
首先看一下以下這段文字: 引用 Feature: Sign in In order to get access to protected sections of the site A user Should be able to sign in Scenario: User is not signed up Given no user exists with an email of "email@person.com" When I go to the sign in page And I sign in as "email@person.com/password" Then I should see "Bad email or password" And I should not be signed in Scenario: User is not confirmed Given I signed up with "email@person.com/password" When I go to the sign in page And I sign in as "email@person.com/password" Then I should see "Your account is not active" And I should not be signed in Scenario: User enters wrong password Given I am signed up and confirmed as "email@person.com/password" When I go to the sign in page And I sign in as "email@person.com/wrongpassword" Then I should see "Bad email or password" And I should not be signed in Scenario: User signs in successfully Given I am signed up and confirmed as "email@person.com/password" When I go to the sign in page And I sign in as "email@person.com/password" Then I should see "Signed in successfully" And I should be signed in Scenario: User signs in and checks "remember me" Given I am signed up and confirmed as "email@person.com/password" When I go to the sign in page And I sign in with "remember me" as "email@person.com/password" Then I should see "Signed in successfully" And I should be signed in When I return next time Then I should be signed in 第一印象就是一段關(guān)于用戶登錄的文檔描述吧? 但實際上,這是一段實際項目中關(guān)于用戶登錄場景的集成測試“代碼” 測試即文檔? 準(zhǔn)確來說,以上代碼是在一個ROR項目中使用Cucumber進行BDD開發(fā)的一個場景描述(測試)。 什么是BDD? http://en./wiki/Behavior_Driven_Development 這不是文本重點,有興趣的同學(xué)可以自行搜索更多文章。 為什么要BDD? 說到BDD,就不得不提TDD(http://en./wiki/Test-driven_development) TDD的開發(fā)流程: Javaeye上有篇老帖子: 什么是“測試驅(qū)動開發(fā)” (http://www./topic/20063 ),點出了為什么要進行TDD的幾個關(guān)鍵問題: 第一,自然語言的描述容易產(chǎn)生歧義 第二,不能自動化地驗證 第三,不能保證文檔與程序同步 TDD強調(diào)的是功能模塊的測試,很多人都愿意使用單元測試,想嘗試TDD,但都會有個問題,不知從哪里開始下手,而我們面向更多的是對一個場景的實現(xiàn),因此BDD應(yīng)運而生,更符合開發(fā)者的思維習(xí)慣。 做開發(fā),不能沒有文檔。我們做開發(fā)時,一般都是先接到一個需求描述(簡單文檔),我們作為開發(fā)者,要做的工作就是實現(xiàn)這個功能(場景)的代碼編寫,例如用戶注冊、用戶登錄、忘記密碼的流程。 而Cucumber就是為我們提供了這么一個工具,讓我們能在用簡單語言描述我們要做的事情同時,也順帶完成了測試代碼的編寫,剩下的就類似是做 填空題一樣,逐步編寫實現(xiàn)代碼,讓所有測試都通過。當(dāng)所有實現(xiàn)代碼都出來了,一個完整的項目也就出來了(文檔+代碼+測試)。這也符合Rails DRY原則,不要做重復(fù)工作。 引用 “軟件工程課講得清楚,只有源代碼的軟件不能算軟件,因為它不可理解、不可維護;源代碼加上文檔,才算是程序員完整地交付了自己的工作?!?/div>
引用自 http://www./topic/20063 我覺得還需要加上測試,才算是一個完整的項目。 怎么在Ruby on Rails 中怎么使用Cucumber進行BDD開發(fā)? 什么是Cucumber? 項目主頁:http:/// 引用 Cucumber is
Aslak Helles?y’s rewrite of RSpec’s “Story runner”, which was originally
written by Dan North. (Which again was a rewrite of his first
implementation - “RBehave”). Early versions of “Story runner” required
that stories be written in Ruby. Shortly after, David Chelimsky added
plain text support with contributions from half a dozen other people.
為什么選擇Cucumber? 在 Rails 已經(jīng)有一些BDD 工具: Rspec (http:///) 使用的測試代碼類似:
雖然也很DSL,但還不夠簡明、直觀,“代碼”的味道還是很重。對比之下,反觀Cucumber的測試“代碼”,即使是團隊中不會編程的角色也能 看得明白在描述什么。如果團隊足夠NB,可以有一個負(fù)責(zé)程序設(shè)計 的leader專門負(fù)責(zé)把需求用Cucumber的features來描述,根據(jù)各人的能力和工作量,再分發(fā)給其下的負(fù)責(zé)編碼的開發(fā)人員進行實現(xiàn)的編碼。 Cucumber的開發(fā)過程 ![]() (from http://www./titles/achbd/the-rspec-book) 具體過程,7個步驟: 引用 1: Describe behaviour in plain text 2: Write a step definition in Ruby 3: Run and watch it fail 4: Write code to make the step pass 5: Run again and see the step pass 6: Repeat 2-5 until green like a cuke 7: Repeat 1-6 until the money runs out 簡單來說就是:寫用例->跑測試->看結(jié)果->寫實現(xiàn)->換個用例,再來一次 具體安裝設(shè)置細(xì)節(jié)略過,Cucumber新手上路可以看視頻: http:///episodes/155-beginning-with-cucumber 或者文字版: http:///episodes/155-beginning-with-cucumber Cucumber能做什么? 看看用Cucumber可以描述、測試多復(fù)雜的場景: 測試發(fā)郵件?沒問題: ![]() 甚至可以把一個用戶進行填寫注冊表單、登錄自己的郵箱、查收激活郵件、點擊激活鏈接的整個故事流程都跑起來: ![]() 又一個常見場景: 已注冊用戶忘記密碼,然后通過點擊“忘記密碼”鏈接,系統(tǒng)發(fā)送激活鏈接到用戶郵箱,用戶通過打開郵箱中的更改密碼鏈接,進入新密碼修改頁面,修改新密碼后能成功登錄: ![]() 用cucumber features -n 命令跑測試的效果: ![]() 一些基本技巧: 在其他場景中,經(jīng)常會用前面測試過的“一個注冊并激活的用戶”,每次都copy一次? Don't repeat yourself! 此時就可以在Cucumnber的steps中把上述過程都封裝成一句話:
實際的封裝steps代碼是: ![]() 第一步是新建一個已激活的用戶,第二步是用這個用戶來進行登錄操作,這樣就得到了一個“注冊并已激活,已經(jīng)成功登錄的用戶” 看看另一個測試用例,也是比較“經(jīng)典”的在一個項目中新建一個todo item的場景: ![]() 其中
的steps實現(xiàn)為: ![]() 通過這樣的封裝,可以用來斷定任意兩個model數(shù)據(jù)對象是否關(guān)聯(lián) 可通用的描述語句為:
一些進階技巧: http:///episodes/159-more-on-cucumber 示范如何做通過設(shè)置模板句法來解決一些重復(fù)、相似的features編寫技巧 如:
但我個人不推薦過多的使用這種技巧,我認(rèn)為Cucumber的features就應(yīng)該保持簡明易懂,去除代碼的味道。features里套用了模 板,人閱讀時就需要用腦“即時編譯”,進行循環(huán)、替換,這就又會給缺乏編程經(jīng)驗的人作為功能描述文檔閱讀時造成障礙,削弱了“測試即文檔”的作用。DRY 不是圣旨,適當(dāng)?shù)闹貜?fù)并不是罪惡。 另外,在cucumber中使用webrat進行測試時,還可以搭配使用Selenium 來測試JS,十分強大,這會是我們下一步的嘗試。 感受: 當(dāng)我第一次看到Cucumber的測試代碼,第一個感覺就是這真的是“代碼”嗎?很奇幻的感覺。 現(xiàn)在感覺Cucumber中的features的本質(zhì)無非是一些用關(guān)鍵詞堆砌的文本段落,然后一個用正則替換的方法來匹配替換真正的測試語句, 很簡單的手段,但最重要的背后的思考,它是bdd所強調(diào)一種開發(fā)風(fēng)格、思維方式。 在用Cucumber開發(fā)了一段時間后,完全沒有感覺不適或強迫感,每次看到測試通過后的一片綠色,心情就很輕松愉快。能很明確每一步在做什么, 而且做完修改后,都能知道修改有沒副作用。Ruby之父說用ruby開發(fā)是happy coding,開始以為just joking,現(xiàn)在真的有這種感覺,現(xiàn)在用Cucumber進行BDD則是多了一個項:happy testting 疑問? I18n怎么處理? Rails 有了Cucumber后,還需要單元測試嗎? http://www./blogs/2009/06/cucumber-rocks-but-its-not-a-replacement-for-unit-tests/ 關(guān)于這個問題,我和同事都認(rèn)為是需要的,只是在一些細(xì)節(jié)上有爭議。 我在實際進行項目開發(fā)時,都是針對一個應(yīng)用場景、案例、用戶故事的思路來進行代碼編寫的,只有當(dāng)流程跑通了(features 的測試通過),下一步才是保證這個流程在一些異常情況下也能得到預(yù)期的結(jié)果(用單元測試來保證,如更多的邊界測試),簡單來說是就 setup features->coding->unit test 同事認(rèn)為,應(yīng)該在寫完cucumber的測試代碼后,再寫單元測試代碼,最后再寫實現(xiàn)代碼,簡單來說是 setup features ->unit test->coding 我不清楚到底那種才是正確的BDD流程,這需要繼續(xù)探討。 以上是我一個月來嘗試BDD的經(jīng)驗分享,作為拋磚,其中或許有片面或錯誤的見解,望有同學(xué)們不吝指教、一起探討。 有研究表明,三個星期可以改變或養(yǎng)成一個習(xí)慣,那你今天開始BDD了嗎? 相關(guān)鏈接: What is Test-driven Development? http://edn./article/29690 Behavior Driven Development Using Ruby http://www./pub/a/ruby/2007/08/09/behavior-driven-development-using-ruby-part-1.html http://www./pub/a/ruby/2007/08/30/behavior-driven-development-using-ruby-part-2.html Introduction to BDD with Cucumber http://www./blog/2009/cucumber-introduction/ A NEW LOOK AT TEST-DRIVEN DEVELOPMENT http://blog./files/BDD_Intro.pdf 本文PDF版(帶排版): http://www./topics/download/69f11949-58ed-33dd-8307-884d280ebad5 不錯,現(xiàn)在一直在用Cucumber 直接支持中文場景描述,而且可以使用場景大綱+例子的方式測試同一的用例不同條件的情況
BDD在rails社區(qū)倒是非常流行,從某種程度上來說,也是得益于rails很方便得能夠DSL帶來得。
這就是我想要的開發(fā)模式。
曾經(jīng)在團隊中用過這種模式,當(dāng)時是以user story驅(qū)動。一個user stroy就類似這里的behavior。效果很好,能讓大家能充分明白開發(fā)任務(wù)和入手點。 不知道這些behavior是如何組織和管理的,是否能全部串聯(lián)起來成為一個真正完整的用例描述文檔。 genki 寫道 個人認(rèn)為 setup features ->unit test->coding 是比較正確的流程??戳撕芏嘟坛贪╮ailscasts里面都是用這個流程,實踐起來也蠻暢快的。
發(fā)現(xiàn)一開始使用BDD的時候不知道從哪入手,寫了很多蹩腳的測試用例,搞得生產(chǎn)力很低下。后面看了很多教程后找到感覺就順暢了,重構(gòu)起來心里也比較有底. 我是這樣考量的,因為實際開發(fā)時,其實很多需求都是模糊不定的,有些細(xì)節(jié)問題只有把流程實現(xiàn)出來后才能發(fā)現(xiàn),需求可能又會變動了,所以我才延遲了ut的編寫。我是等流程完全確定了,才開始編寫一些關(guān)鍵的UT保證邊界值和一些可預(yù)見的異常測試
其實這種 DSL 很像自定語法:
ps:以前還寫了個從 Story 生成/檢查測試骨架的腳本 …… BDD 保證團隊產(chǎn)品質(zhì)量和穩(wěn)定進展還是挺有效的。 但是額外的單元測試不建議寫太多太細(xì) …… 除了測試外,還可以借助一些代碼工具(譬如搞類型推斷的 DRuby ……)進行檢查,減少重復(fù)勞動。 多嘴一下: BDD和ruby是沒半毛錢關(guān)系的,其他語言也有類似的BDD框架,比如StoryQ是.net的BDD框架 ROR項目中使用Cucumber進行BDD開發(fā),Cucumber是用ruby編寫的一個bdd工具
而Cucumber就是為我們提供了這么一個工具,讓我們能在用簡單語言描述我們要做的事情同時,也順帶完成了測試代碼的編寫
什么是Cucumber? 項目主頁:http:///
你若打開Cucumber的項目主頁,就會發(fā)現(xiàn)它的標(biāo)題是: Cucumber - Making BDD fun
|
|