[英]Testing for non-deterministic behavior of python function
我們有一個龐大而復雜的功能,需要確定性。 它是我們公司的主力之一,涵蓋了大量的代碼。 由於python的dict迭代器,這段代碼經常變得不確定。 這已經發生了很多次,並且很難追蹤,並且通常不會立即注意到。 我們想編寫一個自動測試來檢測非確定性,但我不知道該怎么做。
我們已經嘗試在循環中運行函數,並且測試結果總是相同的,但有時,即使函數是非確定性的,函數也會通過此測試,因為dict迭代器的任意但有些一致的排序。
有沒有辦法編寫自動化測試來捕獲這種bug?
也許有一種方法來破解python的dict,以便迭代器在這個測試中是隨機的而不是隨意的? 那樣重復調用函數會更容易發生分歧嗎? 這似乎是一個相當復雜的方法,但我想不出任何其他方式。
編輯:
我們目前正在使用Python 2.7。
我們對各個子模塊進行了單元測試,但由於字典順序的任意但一致的性質,它們通常不會暴露非確定性。
此外,也許非確定性不是描述這個問題的正確方法。 這個函數接受{id:data},但是id的值不應該影響代碼的結果,但是由於python dict的排序,它有時會這樣做。 也許測試這個的最好方法是用隨機值替換id,並檢查在使用不同id的多次運行后輸出是否相同。
如果要隨機化散列種子,可以將-R
標志指定為python:
-R : use a pseudo-random salt to make hash() values of various types be
unpredictable between separate invocations of the interpreter, as
a defense against denial-of-service attacks
一個啦
~$ python -c "print {y:x for x,y in enumerate('foobar')}"
{'a': 4, 'r': 5, 'b': 3, 'o': 2, 'f': 0} #it will always be this
~$ python -R -c "print {y:x for x,y in enumerate('foobar')}"
{'a': 4, 'b': 3, 'r': 5, 'f': 0, 'o': 2}
~$ python -R -c "print {y:x for x,y in enumerate('foobar')}"
{'a': 4, 'b': 3, 'r': 5, 'o': 2, 'f': 0}
~$ python -R -c "print {y:x for x,y in enumerate('foobar')}"
{'f': 0, 'o': 2, 'b': 3, 'r': 5, 'a': 4}
~$ python -R -c "print {y:x for x,y in enumerate('foobar')}"
{'r': 5, 'f': 0, 'o': 2, 'a': 4, 'b': 3}
請注意,此行為是python 3.3中的默認行為。
您可以使用OrderedDict
強制兩個類似的dict
具有不同的“順序”。
使用這些作為代碼的輸入而不是vanilla dict
,您可以可靠地檢查關於dict
順序問題的代碼行為。
例如,此測試有時會失敗(相對很少):
d1 = {'a':1, 'b': 2}
d2 = dict(d1)
j1 = json.dumps(d1)
j2 = json.dumps(d2)
assert j1 == j2:
並且此測試無法預測:
import json
from collections import OrderedDict
d1 = OrderedDict([('a', 1), ('b', 2)])
d2 = OrderedDict([('b', 2), ('a', 1)])
j1 = json.dumps(d1)
j2 = json.dumps(d2)
assert j1 == j2
但是,這可能更適合於小功能的單元測試。 如果您同時測試“大而復雜的函數”,則可能是函數內部生成了dict
,因此對輸入進行操作是不夠的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.