歡迎您光臨本站 註冊首頁

淺析 PHP 官方自動化測試方法

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
本文將從一個測試人員的角度對 PHP 官方的自動化測試方法,自動化測試框架結構,以及具體的實現進行分析和研究。通過實際的例子,向讀者展示 PHP 是如何實現有效的自動化測試以保證其代碼高質量的。讀者通過閱讀本文,可以學習 PHP 官方自動化測試方法和實現,並將這種自動化測試方法應用到自己的開發過程中,提高代碼功能質量。

PHP 官方自動化測試方法簡述

以下介紹以 PHP 最新官方版本 5.2.8 的源碼在 LINUX 系統平台上的分析為例展開。首先來看一下 PHP 的自動化測試腳本 PHPT 腳本。

自動化測試腳本 PHPT 示例

PHP 的測試腳本是以“ .phpt ”為後綴,包含 TEST,FILE,EXPECT 等多個段落的文件,簡稱 PHPT 。在各個段落中,TEST,FILE,EXPECT 是基本的段落,每個測試腳本都必須至少包括這三個段落。其中,TEST 段可以用來填寫測試用例的名字; FILE 段是一個 PHP 腳本實現的測試用例; EXPECT 段則是測試用例的期待值。測試用例的運行中,PHP 將用被測試的 PHP 可執行對象去運行 FILE 段中的測試用例,用實際的結果去比對測試用例中 EXPECT 段所列的期待值;如果實際結果和期待值一致,則測試通過;如果不一致,則測試失敗。

表 1 列出的是常用的段落名和其相應的填充內容說明。


表 1. PHP 測試腳本中的段落說明

段落名 填充內容 備註
TEST 測試用例名稱 必填段落
ARGS FILE 段的輸入參數 選填段落
SKIPIF 跳過這個測試的條件 選填段落
POST 傳入測試腳本的 POST 變數 選填段落。如果使用 POST 段,建議配合使用 SKIPIF 段,如:
--SKIPIF--
<?php if (php_sapi_name()=='cli') echo 'skip'; ?>
GET 傳入測試腳本的 GET 變數 選填段落。如果使用 POST 段,建議配合使用 SKIPIF 段,如:
--SKIPIF--
<?php if (php_sapi_name()=='cli') echo 'skip'; ?>
INI 應用於測試腳本的 ini 設置 選填段落。例如 foo=bar 。其值可通過函數 ini_get(string name_entry) 獲得。
FILE 測試腳本語句 必填段落。應用 PHP 語言書寫的腳本語句。其執行的結果將與 EXPECT* 段的期待值做對比。
EXPECT 測試腳本的期待值 必填段落
EXPECTF 測試腳本的期待值,可用函數 sscanf() 中的格式表達期待值 EXPECT 段的變體
EXPECTREGEX 測試腳本的期待值,可用正則式表達期待值 EXPECT 段的變體

以官方包里自帶的測試腳本 “ 001.phpt ” 為例(見清單 1),從 TEST 段的內容看來這是一個對 PHP 版本進行驗證的測試用例。 SKIPIF 段的內容寫在了 “ skipip.inc ” 文件里。在 FILE 段里,測試用例將環境變數 TEST_PHP_EXECUTABLE 里設置的那個 PHP 的版本列印出來,這個結果將和 EXPECTF 中的字串進行格式匹對。


清單 1. PHPT 測試腳本 “ 001.phpt ” 示例

			--TEST--    version string    --SKIPIF--    <?php include "skipif.inc"; ?>    --FILE--    <?php      $php = getenv('TEST_PHP_EXECUTABLE');      var_dump(`$php -n -v`);      echo "Done\n";    ?>    --EXPECTF-- 	   string(%d) "PHP %s (cli) (built: %s)%s    Copyright (c) 1997-20%d The PHP Group    Zend Engine v%s, Copyright (c) 1998-20%d Zend Technologies    "    Done

如何運行 PHP 自動化測試腳本

在運行測試腳步前,首先要將被測試的 PHP 源碼編譯為可執行對象。

然後要導入若干環境變數。表 2 中介紹了主要的幾個環境變數如何設置。


表 2. PHP 自動化測試中的環境變數設置

環境變數名 環境變數值 例子
TEST_PHP_EXECUTABLE 設定被測試對象 PHP,或者 “ auto ” 。當設置 “ auto ” 時,如果是 CGI 模式,即為 “ ./sapi/cgi/php-cgi ” ;如果是 CLI 模式,即為 “ ./sapi/cli/php ” 。 TEST_PHP_EXECUTABLE=
$HOME/php-5.2.8/sapi/cli/php
TEST_PHP_DETAILED 設定是否需要詳細的日誌輸出。設置值為 1 或者 0 。 TEST_PHP_DETAILED=1
TEST_PHP_USER 設定是否需要特製的用戶目錄。 TEST_PHP_DETAILED= “ /usr/test1 ”
TEST_PHP_LOG_FORMAT
設定日誌的格式。設置值為 “ LEOD ” 子串的子集。其中 L 代表測試后需要生成 “ .log ” 文件,E 代表 “ .exp ” ,O 代表 “ .out ” ,D 代表 “ .diff ” 。 TEST_PHP_LOG_FORMAT="LD"

在本例中,在 Bash 環境中設置環境變數如下:


清單 2. 設置環境變數示例

export HOME=/home/user_dir/    export TEST_PHP_EXECUTABLE=$HOME/php-5.2.8/sapi/cli/php    export TEST_PHP_DETAILED=1    export TEST_PHP_LOG_FORMAT="LEOD"

經過這樣設置后,被測試的 PHP 可執行對象就是放在目錄 “ $HOME/php-5.2.8/sapi/cli/ ” 下編譯好的那個 “ php ” 可執行文件。

執行測試前,還需將測試腳本 PHPT 編輯好,存為 “ .phpt ” 文件。這裡以官方包里自帶的測試腳本 “ 001.phpt ” 為例,運行如下:


清單 3. PHPT 測試總結報告實例

bash-2.03$ cd $HOME/php-5.2.8/    bash-2.03$ $HOME/php-5.2.8/sapi/cli/php run-tests.php  \    $HOME/php-5.2.8/sapi/cli/tests/001.phpt

如果該測試用例的實際輸出與期待值一致,則在屏幕上輸出測試結果如下:


清單 4. PHPT 測試總結報告實例

=====================================================================    CWD         : /home/user_dir/php-5.2.8/sapi/cli/php    PHP         : /home/user_dir/php-5.2.8/sapi/cli/php    PHP_SAPI    : cli    PHP_VERSION : 5.2.8    ZEND_VERSION: 2.1.0    PHP_OS      : Linux rhas05 2.6.9-55.ELhugemem #1                          SMP Fri Apr 20 17:20:11 EDT 2007 i686 i686 i386 GNU/Linux    INI actual  :    More .INIs  :    Extra dirs  :    =====================================================================    Running selected tests.    PASS Test version string [001.phpt]    =====================================================================    Number of tests :    1                 1    Tests skipped   :    0 (  0.0%) --------    Tests warned    :    0 (  0.0%) (  0.0%)    Tests failed    :    0 (  0.0%) (  0.0%)    Tests passed    :    1 (100.0%) (100.0%)    ---------------------------------------------------------------------    Time taken      :    0 seconds    =====================================================================

如果該測試失敗了,則除了屏幕輸出失敗結果外,當前運行目錄下還會生成若干文件,以供用戶分析測試失敗的原因。生成的日誌文件的種類是由環境變數 TEST_PHP_LOG_FORMAT 設定的,詳見表 2 。如果設定的是 “ LEOD ” 則生成日誌文件包括表 3 中列出的五種文件。


表 3. PHP 自動化測試的輸出腳本文件

日誌文件名 日誌文件內容 對應的TEST_PHP_LOG_FORMAT里的設置
001.out 運行測試語句后得到的實際輸出結果。 O
001.exp 腳本中的期待結果,即測試腳本中 EXPECT* 段的內容。 E
001.log 實際運行的輸出結果和腳本中的期待結果,即 “ .exp ” 和 “ .out ” 的合集。 L
001.diff 實際運行的輸出結果和腳本中的期待結果通過 diff 命令得到比對后的結果。 D
001.php 實際執行的 PHP 測試語句,在測試中解析測試腳本的 FILE 段得到。 總會生成

上面的例子是一次只運行一個腳本。 PHP 也支持多測試腳本一起運行。表 4 列出了三種 PHP 支持的測試方式。


表 4. PHP 自動化測試方式

測試方式 參數 舉例
只執行單個測試用例 測試腳本名 001.phpt 002.phpt
執行某個目錄下的測試用例 測試用例的目錄名 test_dir/
執行某個文件中列出的測試用例 -r 加列舉測試用例的文件名 -r record_file





PHP 自動化測試框架的原理和實現

在清單 3中的運行示例中,實際的執行語句是 “ $HOME/php-5.2.8/sapi/cli/php run-tests.php $HOME/php-5.2.8/sapi/cli/tests/001.phpt ” 。其中,“ 001.phpt ” 是測試腳本;“ run-tests.php ” 為 PHP 測試的驅動腳本,是官方腳本;而 “ $HOME/php-5.2.8/sapi/cli/php ” 是運行驅動腳本的 PHP 可執行對象。這裡需要指出的一點是,環境變數 TEST_PHP_EXECUTABLE 中設置的 PHP 可執行對象和這裡運行測試腳本中的 “ $HOME/php-5.2.8/sapi/cli/php ” 雖然指向的是同一個可執行對象,但其意義是不一樣的。環境變數 TEST_PHP_EXECUTABLE 中設置的 PHP 是被測試對象,而運行測試中使用的 “ $HOME/php-5.2.8/sapi/cli/php ” 只是為了用來驅動測試腳本運行。

在圖 1 中可以具體的看出 PHP 測試過程中兩個 PHP 可執行對象及兩個 PHP 腳本的關係。在測試的過程中,首先是由 “ $HOME/php-5.2.8/sapi/cli/php ” 去運行腳本 “ run-tests.php ” (第 1 步)。 在 “ run-tests.php ” 腳本中,將解析環境變數的值 “ TEST_PHP_EXECUTABLE =$HOME/php-5.2.8/sapi/cli/php ” (第 2 步)。這裡 PHP 可執行對象是被測試的 PHP 。“ run-tests.php ” 腳本中還將把測試腳本 “ 001.phpt ” 中的 FILE 段解析為 PHP 腳本 “ 001.php ” (第 3 步), 用 “ TEST_PHP_EXECUTABLE ” 設置的那個 PHP 可執行對象去執行 “ 001.php ” (第 4 步)並得到實際輸出結果,在比對實際輸出結果和 EXPECT 段的期待結果后,輸出測試結果(第 5 步)。以上運行過程可以從對 “ run-tests.php ” 腳本的分析中得出。


圖 1. PHP 測試運行關係圖

通過以上實例分析可以看出,PHP 官方測試的自動化主要依賴於 “ run-tests.php ” 腳本和測試用例腳本 PHPT 。而 “ run-tests.php ” 腳本正是 PHP 測試自動化框架的搭建者。從代碼清單 5 中,可以略微看出 PHP 自動化測試框架的主要工作。


清單 5. PHP 自動化測試代碼片段

$test_cnt = count($test_files);     	 if ($test_cnt) {   		 putenv('NO_INTERACTION=1');   		 verify_config();   		 write_information($html_output);   		 usort($test_files, "test_sort");   		 $start_time = time();     		 if (!$html_output) {   			 echo "Running selected tests.\n";   		 } else {   			 show_start($start_time);   		 }     		 $test_idx = 0;   		 run_all_tests($test_files, $environment);   		 $end_time = time();     		 if ($html_output) {   			 show_end($end_time);   		 }     		 if ($failed_tests_file) {   			 fclose($failed_tests_file);   		 }     		 if (count($test_files) || count($test_results)) {   			 compute_summary();   			 if ($html_output) {   			 fwrite($html_file, "<hr/>\n" . get_summary(false, true));   			 }   			 echo "=================================================";   			 echo get_summary(false, false);   		 }     		 if ($html_output) {   			 fclose($html_file);   		 }     		 if ($output_file != '' && $just_save_results) {   			 save_or_mail_results();   		 }             if (getenv('REPORT_EXIT_STATUS') == 1 and preg_match('/FAILED(?: |$)/',   \                       implode(' ', $test_results))) {   			 exit(1);   		 }

在測試前,這個自動化測試的框架按照用戶指定的有效測試文件數目來決定具體將有多少個測試用例,並寫入 test_cnt 變數中以備計數使用。函數 verify_config() 分別用來驗證和準備各種環境變數的設置及 ini 設置。函數 write_information() 將輸出本次測試環境的各種信息,包括被測試 PHP 的版本號,使用的擴展( Extention ),ZEND 版本,INI 設置,測試所在的系統版本信息,以及測試時間記錄。

測試用例的運行發生在函數 run_all_tests() 中調用的函數 run_test() 中。 run_test() 將具體解析測試腳本中各個段落的含義,清除所以上次測試的記錄與設置將乾淨的測試環境準備完畢,並把各種中間文件和日誌文件準備好,然後用環境變數 TEST_PHP_EXECUTABLE 指定的 PHP 可執行對象運行實際的測試語句。最後將運行后的結果和測試腳本中期待值進行比對,如果比對失敗,則將結果信息一一記錄到用戶設置的日誌文件中。

在所有的測試都運行結束后,變數 end_time 將記錄測試的結束時間,並用函數 compute_summary() 計算成功的、失敗的、跳過的等各種情況的測試數目,並將結果輸出。

由此可以總結出,這個自動化測試的框架主要包括如下幾個部分:

  1. 測試前的準備:包括環境準備以及測試腳本的解析等,如對上次測試遺留下的環境的清理,本次測試所必須的環境變數的讀取與設置,對測試參數的解析,測試腳本名的解析,各種輸出文件的準備等等。
  2. 測試中的腳本運行:解析測試腳本中的各個段落,組織出測試語句,執行測試語句,得到實際運行結果。
  3. 測試后的結果比對及輸出:測試后完成實際輸出結果和期待值的比對,包括各種格式化的比對和正則表達式方式的比對。按要求將結果存寫入指定的文件中,並輸出測試結果的總結報告。





PHP 自動化測試方法的應用

了解了 PHP 官方自動化測試的運作方法后,用戶可以創建自己的 PHPT 測試腳本以幫助 PHP 進行函數黑盒測試。然而,應用 PHP 官方自動化測試的思想和框架搭建方法,用戶還可以構建自己的自動化測試工具,以應用於其他程序開發測試中。在定製自動化測試框架時,需要注意的一些問題,而這些問題在 PHP 官方自動化測試框架中就得到了很好的解決。比如:

  1. 測試腳本的結構。 PHP 官方自動化測試框架只需使用一個簡單的 PHPT 腳本,就可完成測試用例所有必須信息的生成。 PHPT 腳本中的段落使測試名,測試條件,測試步驟,期待值等信息一目了然,非常有利於閱讀和分析。當測試人員在測試過程中需要分析某個測試的失敗原因時,只需要打開對應的 PHPT 腳本就能夠清楚地理解測試用例的用意以及具體測試語句。從而大大減少測試人員的分析時間和難度。而且,這種段落式的組織是具有可擴展性的。
  2. 測試環境的保證。在測試中,環境的“乾淨”與否直接影響到測試結果的準確性。好的自動化框架要力爭給測試一個“乾淨”的環境。這裡的環境包括:系統設置的環境變數,用戶設置的環境變數,測試運行中可能用到的臨時文件等。如果前一個測試改變了全局的環境,那麼在這個環境里運行后一個測試所得到的結果就是不準確的。不準確的測試結果可能帶來極高的誤報率。
  3. 測試結果對比中的藝術。在將測試的實際輸出結果和期待結果進行比對中,PHP 官方自動化測試方法巧妙地應用了正則式比對和格式比對方法。這兩種方法的引入使得測試的誤報率大大降低。因為如果沒有正則式比對和格式比對方法,則測試人員只能將當前本次測試期待結果記錄在期待值中,而這種期待值將可能成為測試腳本的硬碼( hard code ),在回歸測試或期待結果是隨機值等情況下造成測試的誤失敗。
  4. 保留充分的日誌信息。測試結束后,對於那些失敗的測試,測試人員要分析失敗的原因。此時,測試日誌將發揮很重要的作用。充分的日誌信息保留了測試失敗的現場,將幫助測試人員儘快找到失敗的原因並報告給開發人員。 PHP 官方自動化測試框架給予用戶靈活的設置方式去選擇需要的日誌種類。在各種日誌中,不僅將實際測試結果保留在了 “ .out ” 日誌文件中,還將 “ .diff ” 留給用戶。“ .diff ” 文件能幫助測試人員更快地發現期待值與實際測試結果的差別,以更快發現測試失敗的問題所在。

然而,在 PHP 官方自動化測試框架中也存在一些對於用戶來說不完美的地方,比如:在測試異常的情況下,不能輸出完整的測試總結報告。如果測試人員需要完成一個長達十個小時的測試,而測試在第九小時發生了異常,但測試卻無法給出所有跑過的測試的測試報告,這將是很惱人的。所以在自動化測試框架的實現中要考慮好測試異常情況下的處理。





結束語

PHP 官方自動化測試方法給黑盒測試人員提供了一個很好的自動化測試框架的範例。測試人員不僅可以利用 PHPT 測試腳本完善對 PHP 的測試,更可以通過學習這個範例構建自己的自動化測試框架和工具,讓測試的自動化更好地服務於測試工作。(責任編輯:A6)



[火星人 ] 淺析 PHP 官方自動化測試方法已經有1166次圍觀

http://coctec.com/docs/linux/show-post-68942.html