我正在研究Coursera的算法,第一部分课程。我必须使用以下API创建RandomizedQueue:
public class RandomizedQueue<Item> implements Iterable<Item> {
public RandomizedQueue() // construct an empty randomized queue
public boolean isEmpty() // is the queue empty?
public int size() // return the number of items on the queue
public void enqueue(Item item) // add the item
public Item dequeue() // delete and return a random item
public Item sample() // return (but do not delete) a random item
public Iterator<Item> iterator() // return an independent iterator over items in random order
public static void main(String[] args) // unit testing
}
问题:如果我无法创建模拟RNG传递到结构中(因为不允许更改API),并且我不想测试私有方法,该如何测试此结构的随机行为?
我尝试过的
我尝试过考虑作为概率问题的预期结果。因此,例如,我将运行以下伪代码测试10,000次:
create new RandomizedQueue
enqueue 100 items (e.g. integers 0 - 99)
deque 1 item
然后,我可以测试100个项目中每个项目出队的频率是否在某个置信区间内(基于二项式分布)。
最佳答案
有些人可能称其为作弊,但我会beg to differ。
单元测试的重点是验证系统的行为。因此,如果测试完全有用,那么它必须是确定性的。否则,您偶尔会得到假阴性,从而降低测试的完整性。 (“哦,如果测试失败也可以。有时会发生...”)
考虑到这一点,如果您没有无法修改API的限制,该怎么办?如果您有德鲁特人,您将如何实施和测试课程?首先创建该实现。您可以将此类设计为完全确定性的。
拥有一个经过测试的有效类之后,只需对您的类实现RandomizedQueue<Item>
as an adapter。
例
请考虑以下设置:
public interface RandomNumberGenerator {
int GetRandomInt();
}
// Identical to RandomizedQueue<T>, except takes a RandomNumberGenerator as a dependency
public class MyRandomizedQueue<Item> implements Iterable<Item> {
public MyRandomizedQueue(RandomNumberGenerator generator) {
...
}
您的测试可以为SUT提供伪造的
RandomNumberGenerator
,并且可以完全控制任何方法的预期结果。在实际的
RandomizedQueue<T>
实现中,您将使用真实的RandomNumberGenerator
实现实例化测试的类(例如,使用java.util.Random
的实现),将其存储为成员变量,并向前进行方法调用。喜欢:public Item dequeue() {
return innerQueue.dequeue();
}
关于unit-testing - (作业)单元测试具有随机行为的类,而无法模拟RNG,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24432338/