簡體   English   中英

測試python函數的非確定性行為

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM