當一個數不是數字時:隨機測試生成器有哪些好處?

博為峰網校發表於2019-07-12

摘要:

我們希望在劃分我們的測試時,我們將考慮所有的場景,但是太容易忽略不常用的用例。這就是隨機測試生成器的好處。我們可能在測試幾十個測試用例後感覺很舒適;這些工具能生成幾百個。隨著更多的東西被扔到牆上,一些有趣的東西更有可能被粘在牆上。

當一個數不是數字時:隨機測試生成器有哪些好處?

在第一個嘗試FsCheck和基於屬性的測試後,我惱火了。

Haskell程式語言已經存在一段時間了,然而我從來不用它。吸引我注意的是一個名為QuickCheck的工具和它引進的演算法。因為我一直工作在.NET領域,我採選用FsCheck做研究,一個F#埠的QuickCheck。我的惱火來自於演示list集合的屬性。

當我們反轉一個列表,然後再反轉一次,我們希望得到初始列表,對嗎?在不考慮這個列表有多長或者包含什麼,這個屬性應該是真的。想象一下當我第一次用FsCheck測試失敗時,我有多麼驚訝。第一次帶有整數列表的測試透過了,但是當我把它變成持有浮點型時,它失敗了。

FSCheck生成隨機值填入列表,然後檢查屬性是否被測試持有。它做了很多很多次測試,為了查詢失敗的值的組合。在整數的用例中,它不僅僅是我們首先考慮到的1、2、3……,還有會被儲存成固定浮點整數、零和負數的最大和最小整數值。我們也需要考慮空列表。FsCheck所有這些都做了。為什麼當我考慮浮點數時,它失敗了?

解釋來自於對浮點值的定義。他們採用一種位的模式,並將該模式解釋為一個帶有小數點的數字。無論如何,並不是所有可能的位元組合都可以用這種方式進行有意義的解釋。我們把這些麻煩的模式NaN定義為:不是一個數。令我驚訝的是,NaN變數可以是逐位相同的,但不相等。讓他們明白這一點。這似乎合情合理,但卻有違直覺——而且很容易被忽視。

我們希望在設計測試的時候,考慮所有這樣的病態情況,但是很容易忽略像NaN這樣的東西。這就是像FsCheck這樣的隨機測試生成器的好處。我們在測試幾十個測試用例後可能感覺很舒服。FsCheck生成幾百個。隨著更多的東西被扔到牆上,一些有趣的東西更有可能粘在牆上。

在FsCheck發現故障之後,它將採取第二步:它試圖減少引發問題所需的資料量。我不詳細討論這第二步,因為我的觀點是,看到像我剛才用NaN描述的那樣的錯誤有助於我們更深入地思考程式碼庫在做什麼——尤其是在將它的測試縮減到最小的形式之後。

在浮點值列表的情況下,我們可能認為NaN業務是假的。我們這樣做甚至可能是正確的。但是執行測試的目的是讓我們考慮程式碼庫。也許我們應該在系統的邊緣新增一些東西來使NaN值出現在系統之外,或者我們應該確保NaN不能從系統內部的任何轉換中產生。

我們的程式碼有缺陷,因為我們對它的思考存在盲點。即使是世界上最大的自動測試用例生成器也會有盲點。令人高興的是,機器和人類有不同的盲點。

像FsCheck或QuickCheck這樣的工具利用了一種不同的測試範例,利用機器的優勢來彌補我們的不足。機器可以透過演算法制定出大量的測試資料集,這些資料集手工組裝起來既昂貴又枯燥。但是他們需要基於屬性的測試來消耗所有的資料。

當我還是一名新程式設計師時,我並不欣賞這一點。我正在研究一個統計應用程式,它嚴重依賴於貝葉斯統計和機率。有一些事情你可以依靠條件機率。首先,機率總是在0到1之間。另一方面,當我們總結所有條件時,我們應該得到一個。無論我們在程式碼中新增什麼,這些屬性是我們可以自動檢查的。

同樣,我最近與一些朋友進行了一次對話,他們正在構建一個計費系統。我問了一些問題:所有的專案都是正數的嗎?我們是否知道許多行專案的小計將超過更少專案的小計?在不考慮求和順序的情況下,總數是否會發生變化?我問,還有哪些屬性是不變的,我們可以斷言。每個這樣的不變數都可以作為基於屬性的測試的基礎。跟你打賭,我肯定會給這個系統一些負的價格。

廣泛的屬性測試可以教會我們很多關於程式碼庫的知識。測試從不確定程式碼庫是無錯誤的,但是測試確實縮小了錯誤可以隱藏的範圍。為了學得更多,我們必須理解測試的作用和它們所顯示的內容。這可能意味著我們應該更多地關注理解我們的測試,而不是僅僅增加少量理解的測試的乘法。就像FsCheck將大型失敗測試簡化為更簡單的表單一樣,我們也應該定期檢查我們的測試套件。

是否每個測試告訴我們的不僅僅是重現過去幾年bug報告的環境?這些測試是否可以重新組織以闡明我們為什麼關心它們?我們的目標應該是策劃測試,以最大限度地從每個測試的成功或失敗中得到理解。

當我對浮點的基於屬性的測試失敗時,NaN讓我感到驚訝。這並不是由於列表倒轉的故障;它失敗的原因是測試中固有的關於如何比較浮點數的假設。這提醒我們尋找與我們的假設相矛盾的資料。我們在測試中加入的驚喜越多,我們的系統就會變得越健壯。這需要結合多種不同的範例和功能來利用每種範例和功能的優勢。

被NaN嚇到似乎是個壞訊息。它讓我們陷入了一個失敗的測試,這個測試只與我們正在測試的程式碼間接相關。但是這樣做會讓我們想起一些我們可能已經忘記的軟體。這樣的提醒會把驚喜變成好訊息。

歡迎加入 51軟體測試大家庭,在這裡你將獲得【最新行業資訊】,【免費測試工具安裝包】,【軟體測試技術乾貨】,【面試求職技巧】... 51與你共同學習,一起成長! QQ                     群:                    755431660

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31407649/viewspace-2650399/,如需轉載,請註明出處,否則將追究法律責任。

相關文章