Chapter 13. 回歸測試

Table of Contents
13.1. 測試評估
13.1.1. 錯誤資訊差別
13.1.2. 區域差別
13.1.3. 日期和時間差別
13.1.4. 浮點數差別
13.1.5. 元組順序差別
13.1.6. "隨機"測試
13.2. 平台相關的比較文件

回歸測試的指導和分析.

回歸測試是一套復雜完整的測試, 用來測試內嵌在 PostgreSQL 裡的的 SQL 實現. 它同時測試標準 SQL 操作和PostgreSQL的擴展SQL. 這個套件最初是 Jolly Chen 和 Andrew Yu開發的,並且由 Marc Fournier 和 Thomas Lockhart 進行了大量的改進和重新封裝. 自 PostgreSQL 6.1 以上開始, 這個回歸測試包含在每個正式發佈版本裡.

回歸測試可以就一套已經安裝好並且在運行的伺服器進行測試, 也可以就制作樹裡面臨時安裝的伺服器進行測試.詳細些說,有 "並行""串行"運行測試之分. 串行樣式順序運行每個測試,而並行樣式啟動多個伺服器程序, 並行地運行一組測試. 並行測試使我們對程序內部通訊和鎖的正確工作有足夠的信心. 由於歷史原因,串行測試通常對一個現存的安裝進行測試,而並行 測試是"獨立"的,不過這麼做沒有什麼技術原因.

制作之後和安裝之前運行回歸測試,你可以在頂級目錄輸入

$ gmake check

(或者你可以進入 src/test/regress 然後 在那裡運行命令.) 這樣將先制作幾個輔助文件,比如平台相關的 "expected(預期)" 文件和一些使用者定義的觸發器函數,然後再運行測試驅動腳本. 最後你會看到類似下面的東西

======================
 All 76 tests passed.
======================

或者是一些關於某項測試失敗的資訊.參閱下面的 Section 13.1獲取更多資訊.

注意: 因為這個測試方法運行臨時的伺服器,所以如果你是 root 使用者, 那這個方法不能運行(伺服器不能以 root 身份啟動). 如果你已經以 root 身份制作了,你就什麼也幹不了. 這時候你應該把測試目錄的權限變成某個使用者可以寫, 然後以那個使用者身份登陸,再開始測試.比如,

root# chmod -R a+w src/test/regress
root# chmod -R a+w contrib/spi
root# su - joeuser
joeuser$ cd top-level build directory
joeuser$ gmake check

(這裡唯一可能的"安全隱患"就是那個使用者可能會背著你 修改回歸測試的結果.用你的常識管理使用者權限.)

如果不是上面那樣,安裝後就可以運行測試.

竅門: 並行的回歸測試會在你的使用者 ID 下啟動相當多的程序. 目前,最大的並發數是 20 給並行測試腳本,這意味著 60 個程序 --- 一個後端,一個psql以及通常還有一個 shell 父程序用於每個測試腳本 的psql.因此,如果你的系統有每使用者的程序數限制,那麼請確保這個 限制至少是 75,否則你就可能在並行測試時看到隨機出現的失敗. 如果你沒有辦法提升該限制,那麼你可以編輯文件 src/test/regress/parallel_schedule,把大的並行測試 套件分割成更容易管理的小組.

小技巧: 在某些系統上,預設的 Bourne 兼容的 shell(/bin/sh) 在管理太多並行的幾程序的時候會出亂幾.這可能導致並行測試鎖住或者失敗. 出現這種情況時,請在命令行上宣告另外一個 Bourne 兼容的 shell,比如:

$ gmake SHELL=/bin/ksh check

如果能用比較好的 shell,那麼你可以象上面那樣修改並行測試計劃.

安裝後(參閱 Chapter 1)運行測試, 初始化一個資料區然後啟動伺服器,象我們在 Chapter 3 裡面描述的那樣,然後輸入

$ gmake installcheck

該測試將與在本地主機和預設連接埠號上運行的伺服器進行連結, 除非你用PGHOSTPGPORT環境變數設定為其它值.

13.1. 測試評估

有一些正確安裝並且具有完整功能的 PostgreSQL可能會在一些回歸測試中 "失效", 這些主要是因為浮點數的形式和時區支援的問題.目前的測試只是簡單的用 diff與參考系統的輸出進行比較, 因而對一些細小的系統區別很敏感. 當一項測試報告"failed"("失敗")時,只要檢查一下預期和實際的結果, 你就會發現區別區別並不大. 當然,我們仍然在努力維護所有我們支援的平台的準確的參考文件, 這樣我們就可以假定所有測試都通過.

回歸測試的實際輸出是在 src/test/regress/results 目錄裡的文件裡.測試腳本使用 diff 以比較 每個輸出文件和存放在 src/test/regress/expected 目錄裡的參考輸出.任何區別都存放在 src/test/regress/regression.diffs 裡面供你檢查.(或者如果你愿意的話,你也可以自己運行 diff.)

13.1.1. 錯誤資訊差別

有一些回歸測試涉及到有意的非法輸入值. 錯誤資訊可能會來自PostgreSQL 代碼或來自主機平台系統過程. 對於後者,資訊可能在平台之間區別比較大,但應該反映相似的資訊. 這些資訊上的差別將會導致一個"失敗"的回歸測試, 我們可以通過檢查文件發現這一點.

13.1.2. 區域差別

如果你在一台已經安裝好了的伺服器上運行測試,而該伺服器是用一種 非 C 的區域設定初始化的,那麼可能因為有排序順序和其它類似的差別 導致的失敗.回歸測試套件處理這種問題的方法是提供可選的結果文件, 這些文件一起處理一大堆的區域.比如,對於 "char" 測試, 預期的文件 char.out 處理CPOSIX區域, 而文件 char_1.out 處理許多其它區域. 回歸測試驅動將自動選取最接近的文件進行成功檢查以及計算失敗差別. (這就意味著回歸測試不能檢測該結果對於配置的區域是否合適. 該測試將簡單地選取一個運轉得最好的文件.)

如果由於某些原因,現有的預期文件無法覆蓋一些區域,那麼你可以 增加一個新文件.命名綱要是 testname_digit.out. 實際的 digit 是什麼並不重要.要記住回歸測試驅動將認為所有 這樣的文件都是有效的測試結果.如果測試結果是平台相關的, 那麼應該使用在 Section 13.2 裡描述的技巧.

13.1.3. 日期和時間差別

如果你在夏時制時間切換的那天,或者是之前或之後一天運行測試,那麼 在 horology 測試中的一些查詢會失敗, 這些查詢假設在昨日午夜,今日午夜和明日午夜之間的差距正好時 24 小時 -- 如果在夏時制切換的時候這個數值時錯誤的.

大多數日期和時間結果依賴於時區環境變數。參考文件是為時區 PST8PDT (伯克利,加州)準備的,因而如果測試沒有設定為那個時區是顯然會失敗的。 回歸測試的驅動器把環境變數 PGTZ設定為PST8PDT以保証正確的測試。 不過,你的系統必須為PST8PDT提供庫支援, 否則與時區相關的測試將會失敗.

$ env TZ=PST8PDT date

上面的命令應該傳回PST8PDT時區的目前時間.如果沒有能用的 PST8PDT資料庫,那麼你的系統可能會傳回 GMT 的形式的時間. 如果沒有可用的PST8PDT資料庫,那麼你可以明確設定時區規則:

PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ

有些系統不能接受我們推荐的顯式設定時區的語法﹔ 在這樣的機器上你可能要用不同的 PGTZ設定。

有些使用舊的時區庫的系統在對PDT1970 年前的時間使用夏時制時會出毛病, 導致PDT1970 年以前的時間顯示為PST。 這會導致在測試結果裡的本地化區別。

如果你在改為夏時制的日切日或者該天的前天或者後天測試時, 在 "timestamp" 測試裡的一些查詢可能失敗. 這些查詢假設昨天午夜, 今天午夜和明天午夜之間的間隔是精確的 24 小時... 如果是夏時制開始或結束的日切日,這些(假設)是錯的.

13.1.4. 浮點數差別

有些測試涉及到對表中的資料列進行 64位(double precision) 計算的問題. 我們觀察了涉及到計算double precision欄位的數學函數的 結果的差別. float8geometry(幾何類型)測試尤其容易在不同平台之間產生小差別。 這時需要肉眼對這些差別進行比較, 以判斷這些差別究竟有多大,我們發現是在小數點右邊10位數。

有些系統把負零顯示為 -0,而其它的只是顯示 0

有些系統在pow()exp() 出錯時產生的信號與目前 Postgres代碼裡期望的機制不一樣.

13.1.5. 元組順序差別

你可能會看見同樣的元組以與預期文件的不同的順序輸出.在大多數情況下, 嚴格說來這不算臭虫.大多數回歸測試腳本都不會迂腐到在每個 SELECT 中都使用 ORDER BY 的地步,因此根據 SQL 規範裡的詞匯的說明,它們的結果集的順序 並非定義得非常好的.尤其是因為我們是在同樣的資料上運行同樣的查詢, 因此我們在所有平台上通常都獲得同樣的結果, 因此即使缺少 ORDER BY 也不算什麼大問題. 不過有些查詢的確存在跨平台的排序問題. (如果你使用了非 C 的區域設定,也可能造成排序差異的問題.)

因此,如果你看到一個排序差異,應該不是什麼要擔心的問題(除非 出問題的查詢的確使用了 ORDER BY).不過,如果有這樣的現象,請告訴我們, 這樣我們就可以在那條查詢上加一個 ORDER BY, 這樣我們就可以在以後版本裡消除著種偽"失敗"

你可能會問,為什麼我們不對所有回歸測試的 SELECT 進行排序 以一次性消滅所有這類問題. 原因是這樣做只能讓回歸測試用處更少,而不是更多,因為它們會試圖使用 那些生成順序結果的查詢規劃,而不再使用那些不排序的查詢規劃.

13.1.6. "隨機"測試

"隨機"測試腳本裡至少有一個測試會產生隨機結果. 這會導致回歸測試中的隨機測試失敗(可能每五次到十次出現一次). 輸入

diff results/random.out expected/random.out

會產生僅僅一行或幾行差別. 你不必擔心這些,除非隨機測試在重復測試中總是失敗. (另一方面,如果在多次回歸測試中隨機測試 從不 失敗,你可能也 應該 擔心.)