我目前正忙於在Ruby中實現有趣的數據結構,並且遇到了沒有可預測輸出的測試函數的問題。我目前工作的一個Bloom Filter,我已經包括下面的完整性實施:測試不可預知的功能
require "zlib"
class BloomFilter
def initialize(size=100, hash_count=3)
raise(ArgumentError, "negative or zero buffer size") if size <= 0
raise(ArgumentError, "negative or zero hash count") if hash_count <= 0
@size = size
@hash_count = hash_count
@buffer = Array.new(size, false)
end
def insert(element)
hash(element).each { |i| @buffer[i] = true}
end
def maybe_include?(element)
hash(element).map { |i| @buffer[i] }.inject(:&)
end
private :hash
def hash(element)
hashes = []
1.upto(@hash_count) do |i|
hashes << Zlib.crc32(element, i)
end
hashes.map { |h| h % @size }
end
end
一個與布隆過濾器的問題是,它有虛假地返回true的返回誤報的可能性包含從未插入過濾器的元素。
有時候,過濾器行爲的方式,是容易測試:
b = BloomFilter.new(50, 5)
b.insert("hello")
puts b.maybe_include?("hello") # => true
puts b.maybe_include?("goodbye") # => false
但是它有時雄鹿的趨勢,並以不可預測的方式行事。 (我已經減少了緩衝區的大小,這裏迅速找到發生衝突。)
b = BloomFilter.new(5, 4)
b.insert("testing")
puts b.maybe_include?("testing") # => true
puts b.maybe_include?("not present") # => false
puts b.maybe_include?("false positive") # => true (oops)
因此突然間,我們有字符串「假陽性」提供......假陽性。我的問題是我們如何測試這個?
如果我們選擇恰好與我們的測試工作,然後我 覺得測試值變得過於脆弱。例如,如果我們更改了散列函數 ,那麼我們可能仍然有一個完美正確的Bloom 由於我們選擇了 來測試原始實現的值,所以開始失敗某些測試的篩選器。
我的第二個想法是,以測試該過濾器在預期 方式僅通過檢查,我們通過改變 內部緩衝區的散列函數的數量和規模得到大致從它的expected number of false positives 行爲。雖然這種方法可能會測試整個粗糙過濾器的正確性,但我擔心它將無法捕獲導致其針對個別情況報告不正確值的錯誤(例如,假 負面因素)。
我是不是太悲觀測試它上面的兩種方法的效果還是我失去了一個方法來測試類,如布隆過濾器,其輸出是不可預測的?