行為驅動開發在 Python 開發測試中的應用

peso2276 7年前發布 | 12K 次閱讀 測試技術 Python 驅動開發 Python開發

行為驅動開發 (BDD) 簡介

行為驅動開發是什么?

說到行為驅動開發(BDD),無可避免的要提到敏捷里面的測試驅動開發(TDD),TDD 的主要思想是“代碼即文檔”,其倡導的流程是根據設計編寫測試-> 實現設計的功能 -> 用測試代碼驗證 -> 重構實現代碼 -> 改善設計 -> 再次回到根據改善的設計編寫測試。

圖 1 基于 TDD 的項目開發流程

圖 2 用戶登錄場景測試

圖 3 非法用戶登錄場景

圖 4 合法用戶登錄場景

有了這些場景描述,測試人員可以通過一些 BDD 測試框架將上面的故事轉成測試代碼, 開發者實現產品功能,保證所有的測試案例成功通過。

為什么要進行行為驅動開發?

如上可以看出,行為驅動開發的根基是一種“通用語言”,類似于用一個最小化的詞匯表來定義,其中這些詞匯具有準確無誤的表達能力和一致的含義。

as 指明系統行為是為什么角色而定義的。

In order to 和 I want 定義了行為的范圍,表明了想達到的目的,想做的事情。

Given 給出了準備要測試的對象和測試環境。

When 調用要測試的業務方法。

Then 對測試結果進行驗證

這種通用語言同時被需求,開發,測試和客戶等項目相關人員用來定義系統的行為。這樣子大家看到的描述一致,內容一致,最大程度的交付出符合用戶期望的產品,避免表達不一致帶來的問題。

圖 5 使用行為驅動開發的開發狀態圖

Python BDD 測試框架的搭建

Lettuce 簡介

為什么在這里要提到 Lettuce 呢?看它的 官網 介紹,這個框架在 Python 語言的測試應用堪比 Ruby 語言領域的 Cucumber,它可以對 Python 項目進行自動化測試,值得注意的是這里的測試用例是純文本的,具有很好的可讀性。這樣的話,即使是不懂編程的人也可以站在系統或用戶的角度來寫測試用例,并且在項目開發過程中,這個自動化測試用例可以很容易的修改、擴充,開發人員也能很快的調整,從而保證測試用例順利通過。

搭建 Lettuce 測試框架

前面已經說了很多 Lettuce 的作用和好處,那么下面我們來看下如何在自己的環境上搭建這樣一個測試框架。接下來筆者將給出 Redhat Linux + Python2.6 這樣的環境下的搭建步驟。

首先,Python 上安裝 package 的時候,一般都會建立一個 Virtualenv。

如何來理解 Virtualenv 呢? V irtualenv 是一個 Python 環境管理工具,它可以創建獨立的 Python 環境,多個 Python 相互獨立,互不影響。簡單的來說,你可以將它看做是一個個隔離的沙盒,每一個沙盒之間相對獨立,保持著一個相對獨立干凈的環境。可能這樣說,你還沒有理解到它的實際好處,試想一下,你之前有一個項目 A 需要依賴 Django1.2.5, 而現在又有一個新的項目 B,它需要依賴 Django1.3,這時除了把它們放到不同的沙盒里面,你還可以重新搭一套 Python 環境,甚至于需要換臺機器,這樣沙盒的好處就顯而易見的了,應該沒有人會不喜歡這么簡單的方法。好的,既然喜歡,那么如何來安裝并激活呢?

1.install virtualenv

easy_install virtualenv-1.6.4.tar.gz

2.create virtual environment (vevn)

virtualev [vevn_folder] –no-site-packages

3.enter into [venv_folder]

source bin/active

僅需要以上 3 個命令就可以安裝并激活 Virtualenv 了,值得注意的是,這個 Virtualenv 看上去就是個文件夾 [vevn_folder],可以很容易地刪除、重建等等,但在每次使用前都需要將它激活。

另外我們這里使用了 easy_install 命令,這是 setuptools 帶的一個命令,其中 setuptools 是一個非常好的應用于 Python 的安裝工具,使用它,可以使用如上很簡單的命令來安裝所需要的 package。如下就是安裝 setuptools 和 Virtualenv 的步驟圖:

圖 6 安裝 setuptools

圖 7 安裝并激活 Virtualenv

我們可以從網站上下載這些需要的包到本地,當然也可以直接用 setuptools 來安裝,如果本地沒有安裝包,它會自動下載 package 的最新版本來安裝。不管怎么樣,需要注意的是,由于這些包之間存在依賴關系,因此需要按照特定順序來進行安裝。以下就是所有依賴包的順序安裝:

表 1 Lettuce 順序安裝包

包名 下載鏈接及安裝方式 簡要說明
Nose url: http://code.google.com/p/python-nose/
easy_install nose-1.1.2.tar.gz
Nose 是最流行的針對 Python 的測試庫之一
Mox url: http://code.google.com/p/pymox/
easy_install mox-0.5.3.tar.gz
Mox 是 Python 編程語言的單元測試框架

Sphinx

url: https://pypi.python.org/pypi/Sphinx/1.0.7
Sphinx 有 4 個依賴包,需要先提前安裝依賴
easy_install docutils-0.8.tar.gz
easy_install Jinja2-2.6.tar.gz
easy_install lxml-2.3.tar.gz
easy_install Pygments-1.4.tar.gz
easy_install Sphinx-1.0.7.tar.gz
Sphinx 常用于生成文檔,Lettuce 測試框架的測試結果顯示依賴于它

Lettuce

url: https://pypi.python.org/pypi/lettuce/0.1.31
Lettuce 安裝時提示缺少 4 個依賴包,所以先安裝好這幾個包。
easy_install pycrypto-2.3.tar.gz
easy_install paramiko-1.9.0.tar.gz
easy_install Fabric-1.5.3.tar.gz
easy_install Jinja2-2.6.tar.gz
easy_install lettuce-0.1.31.tar.gz
Lettuce 是 Python 常用的 BDD 測試框架

安裝完之后可以做如下的簡單測試來確定是否安裝成功。

在命令行里直接輸入 Lettuce, 如圖所示,如果顯示類似找不到 features 的提示信息,那么恭喜你已經成功安裝上了 Lettuce 測試框架。

圖 8 Lettuce 安裝驗證

1. 如果建立的有 Virtualenv,那么在做任何操作之前必須要先激活它;

2. 對于 Python 來說,特別是要注意包之間的依賴,如果不清楚,可以先查查,實在不行,用 easy_install 這個工具來安裝,它會自動檢查依賴關系,如果缺失則會自動從網上下載最新的匹配版本并進行安裝,但遇到依賴關系復雜而網絡狀況又不好的時候,最好手動下載放到本地目錄,就像本文中用到的包一樣。

基于 BDD 思想的 Python 開發測試過程

接下來這一章,我們希望通過生動詳細的案例來講述測試用例及測試腳本的編寫和運行過程。比如說我們想自己實現一個計算整數 n 次方的計算器,當然這個程序可能比較簡單,但這里為了更好的理解 BDD 的思想,我們假設它很復雜,剛開始不知道怎么實現,我們就只好先寫測試用例,然后一步步的修改代碼讓所有可能的用例通過。接下來本文將以 4 個迭代詳細描述該過程。

測試用例及測試腳本的編寫

在寫測試用例時,就參照前面章節所介紹的,用一些簡單無異議的最小詞匯組來描述可能的用戶場景。

迭代 1

先給出一個 n 次方計算器程序的接口 computePow.py,如下所示,我們不知道如何實現它,所以讓計算結果都為-1。

圖 9 計算程序接口定義

圖 10 測試用例描述

圖 11 解釋腳本

好了,至此一條簡單的測試用例已經完成,我們來讓它運行一下,進入到文件所在目錄,使用命令:lettuce computePow.feature,運行結果如下圖所示。

圖 12 運行測試用例

運行結果顯示,總共運行了一個 feature 和一個 scenario,都運行失敗,scenario 中共有 3 個 step, 其中 2 個成功運行,還有一個失敗,從圖中可以看到失敗的地方以及具體堆棧信息。

從這里就可以體會 BDD 的好處,對于測試人員來說能很清楚的明白問題出在哪一步,可以找誰去溝通;而這些錯誤信息也能很好的幫助開發人員解決問題;另外下面的統計數字也能很清楚地看到測試通過百分比。

既然測試用例跑失敗了,接下來我們就修改代碼讓用例成功跑通。通過數學計算,我們知道 1 的 0 次方是 1,因此我們修改計算程序 computePow.py,讓它返回 1,修改完之后運行一下,發現這時測試用例已經完全跑過。如下所示:

圖 13 修改后計算程序接口

圖 14 再次運行測試用例

迭代 2

接下來,我們就可以考慮擴展測試用例,為讓測試更完備,在這里我們增加了 3 個計算,分別是 3 的 0 次方為 1,2 的 1 次方為 2 和 5 的 0 次方為 5,新增用例如下所示:

圖 15 測試用例功能擴展

運行該用例之后,發現在 Scenario: pow(2, 1) 和 Scenario: pow(5, 1) 出錯,如下所示,該次運行有 2 個 scenario 成功運行,2 個失敗,從運行結果可以很容易地知道是哪一個步驟出錯。

圖 16 測試用例功能擴展后運行結果

因此我們修改計算程序 step.py,如下所示:

圖 17 第 3 次修改計算程序接口

再次運行命令 lettuce computePow.feature, 發現我們的這 4 個 Scenario 和 12 個 step 都能成功跑過。

迭代 3

到這里我們才測試了 4 個簡單用例,接下來我們再增加 2 個稍微復雜些的用例,計算 2 的 3 次方為 8,3 的 2 次方為 9,新增用例如下所示:

圖 18 測試用例第 2 次功能擴展

運行該用例之后,發現在新增的 2 個用例處 Scenario: pow(2, 3),Scenario: pow(3, 2) 出錯,因此我們修改計算程序 computePow.py 以讓用例通過,如下所示:

圖 19 第 4 次修改計算程序接口

再次運行命令 lettuce computePow.feature, 發現我們的這 6 個 Scenario 和 18 個 step 都能順利跑過。

迭代 4

至此我們的計算器小程序已經順利跑過 6 個用戶場景,如果再新增用例的話,就可仿照上述 3 個迭代過程來添加,但是這有一個問題,隨著用戶場景增多,我們發現 computePow.feature 變的越來越長,難以管理,仔細觀察一下,發現每個場景的 step 很相似,也就說我們寫了很多重復的描述信息,針對這一問題,Lettuce 測試框架可以用 scenarios outlines 來解決,如下圖所示:

圖 20 使用 scenarios outlines 描述測試用例

行為驅動開發在 Python 開發測試中的應用

這樣的寫法可以使測試用例在依然能表達豐富的信息的情況下變的很精簡,且更容易管理和擴展。

測試腳本運行及自動化

測試腳本如何運行在前一章的實例中已經提到,只需要簡單命令 lettuce computePow.feature 就可以。這樣它就會在當前路徑下搜尋與每一個 step 匹配的腳本來解釋執行。注意的是,這里的測試用例和測試腳本的名字沒有關聯性。如果當前路徑下有多個測試用例文件,也就是說有很多*.feature 文件,就可以用 lettuce ./ 或者 lettuce *.feature 來批量執行。

到此想必大家已經對 BDD 在 Python 領域的開發測試過程以及測試框架搭建已經有一個形象的理解,在前面的實例中也體會到了這種方法的好處。最后要提到的自動化實質上是這種方法的另外一個好處,假設我們的計算器程序將分布于不同的 OS 上,需要對這些環境都進行測試,又或者說我們的計算器程序需要升級用 Python 的更高版本等等,這樣我們就要將測試環境和開發環境分離,在我們的案例中,可以看到測試用例和計算器程序是彼此獨立的,這樣我們只用做很少的工作,譬如寫一些簡單的腳本,然后在測試環境上通過 set 或 export 設置遠程開發環境的運行變量就能很輕易的讓它自動化運行。

總結

本文首先對行為驅動開發做了一個簡介,接下來通過實例圖文并茂地講述了如何將這一思想靈活運用到 Python 領域,同時中間還穿插了測試框架 Lettuce 的安裝及運行。在此,希望本文能起到一個拋磚引玉的作用,增進讀者對 Python 和 BDD 的了解,有興趣的讀者可以進行深入研究,將其靈活應用到項目實踐中。

BDD,即行為驅動編程,是 TDD 的一個改進版本,BDD 本質上也是 TDD,但是比 TDD 要更加自然一些,更 DSL 化。系統業務專家以及測試開發人員一起合作,分析出軟件的需求,然后像故事一樣描述出一個個具體可執行的 Behavior;之后開發者負責填充這些故事的內容,測試人員負責檢驗故事結果的正確性。一個比較簡單的案例即用戶登錄場景測試:作為普通用戶,我在登錄網站時,就牽扯到用戶名和密碼的校驗。同樣的故事就因此會有不同的場景發生:如果是一個合法用戶來發出請求,那么又將是另外一個場景:人云“工欲善其事,必先利其器”,因此在詳細介紹基于 BDD 思想的 Python 開發測試過程之前,我們先來看一下如何搭建一個有效易用且穩定的測試框架。圖 7 安裝并激活 Virtualenv到這里,算是打好了基礎,回頭再看看,安裝時需要注意的有以下 2 個方面:接下來先來一條最簡單的測試用例 computePow.feature,如下圖所示,這個測試用例在上面首先說明了這是一個計算 n 次方的 feature,另外還簡單說明了作者,目的等,最重要的是用 3 個步驟很清楚的描述了一個用戶場景,即 1 的 0 次方為 1。不用再多說,想必大家已經感受到這樣的測試用例的好處,簡單明了,易讀性高,信息量大,便于維護。當然到此為止,這個看上去很清晰明了的測試用例只是對用戶來說是這樣的,計算機是如何理解的呢?這就需要我們對這些 step 做轉換,從而使程序正確理解用戶行為。如下所示我們定義了一個解釋腳本 step.py:這個 step.py 需要和前面的測試用例 computePow.feature 結合來看,首先 step.py 里面定義了 3 個方法,每個方法是和 factorial.feature 文件里面的用戶場景的每一個步驟對應,而這個對應規則就是靠方法上面的 @step(…) 所標識的正則表達式來匹配的,其中有正則表達式的地方,如 (d+),表示是參數帶入,比如在方法 have_the_number 中,上面的匹配規則有兩個 (d+),表示這里有兩個數字參數,因此該方法也帶了兩個形式參數 bottomnumber 和 uppernumber。運行時,這兩個參數值將從測試用例對應的 step 中獲取,即 Given I have the bottomnumber 1 and the uppernumber 0,也就是說實際參數將是 1 和 0。另外需要注意的是我們強烈支持代碼的可讀性,因此這里 step.py 中的方法名都很容易理解。

 

來自:http://python.jobbole.com/87412/

 

 本文由用戶 peso2276 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!