我正在研究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/

10-09 21:03