我目前正在搞乱在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)
所以突然间我们有了字符串&#34;误报&#34;提供......误报。我的问题是我们如何测试这个?
如果我们选择刚刚发生的值来处理我们的测试,那么我 感觉测试变得太脆弱了。例如,如果我们改变 哈希函数然后我们可能仍然有一个完全正确的布卢姆 由于我们选择的值,过滤器开始失败某些测试 测试原始实现。
我的第二个想法是测试过滤器的行为是否符合预期 通过检查我们大致得到expected number of false positives的方式 通过改变散列函数的数量和大小 内部缓冲区。虽然这种方法可能会测试整体粗糙度 过滤器的正确性我担心它无法捕获 导致它报告个别情况的错误值的错误(例如false 底片)。
我对上面测试它的两种方法的有效性过于悲观,还是我错过了测试输出不可预测的Bloom Filter等类的方法?
答案 0 :(得分:2)
你选择刚刚发生工作的价值是对的,这是一个坏主意。但是,你的第二个想法并不是那么糟糕。
您应该始终能够测试应该在bloom过滤器中的值是否存在。您可以随机生成许多字符串,并检查阈值数量是否为误报。这样,如果您更改散列函数,您的单元测试仍然可以工作,并且仍会报告过滤器具有可接受的误报率。
答案 1 :(得分:0)
测试是关于确认您的期望。如果你不能自己解释Bloom过滤器会返回什么(考虑到你提到的脆弱性),你不能期望有这样的期望。 (我发誓,我并不想制造双关语:P)
我的第一个直觉是在所有有趣的哈希算法上确认N个生成输入的误报率。这样可以自动实现您手动执行这些测试的安全性。
为实现这一目标,我建议您将测试代码考虑在内,以便表达如下简单:
&LT;警告&GT;未验证的代码&lt; / warning&gt;
class BloomFilterTestCase << TestCase
def bloom_incidence(alg, pop, false_positives)
define_method("test_bloom_incidence_${alg}_${pop}_${false_positives}") do
# code code code
end
end
bloom_incidence :naive, 50, 0.05
end
答案 2 :(得分:-1)
布隆过滤器是一种节省空间的概率数据结构,用于测试元素是否是集合的成员。假阳性是可能的,但假阴性不是。
仅仅从Bloom过滤器的描述来看,应该很清楚,测试误报是没有意义的。它本身是未定义的,正面测试的结果是什么,所以你无法对期望某个结果的它进行测试。您可以保证并因此测试的唯一事项是: