嘲笑随机数

问题描述 投票:4回答:1

我的应用程序使用遗传算法来进化神经网络。在为(随机)突变算法开发单元测试时,我希望确保对于给定的随机值,能发生正确的突变。

在问题中 此处 对于涉及随机性的单元测试算法问题,最流行的答案是使用嘲讽。这在我看来是非常明智的,但我的问题是,是否有人对如何做到这一点有可靠的建议。

以下是我目前实现这个目标的方法。我定义了一个 interface 用于我的随机性生成器(为了说明问题,这里高度简化)。

public interface Mutator {
    float randomSynapseWeightChange();
    float randomSynapseThresholdChange();
}

在主程序中,这个接口有一个实现,它封装了 Random. 在我的单元测试框架中,我使用。

public class TestMutator implements Mutator {
    List<Float> synapseWeightChanges = new ArrayList<>();
    public void addTestSynapseWeightChange(float weightChange) {
        synapseWeightChanges.add(weightChange);
    }
    public float randomSynapseWeightChange() {
        return synapseWeightChanges.remove();
    }
}

我的单元测试是这样的

@Test
public void testDecreaseSynapseWeightMutation() {
    TestMutator mutator = new TestMutator();
    mutator.addTestSynapseWeightChange(-0.5);
    world.setMutator(mutator);
    Synapse synapse = new Synapse(new Neuron(), 0.1);
    synapse.mutate();
    assertEquals("Weight has decreased during mutation", -0.4, synapse.getWeight());
}

这真的不是一个特别优雅的解决方案 单元测试依赖于知道代码需要多少个随机数。对于涉及到几个模拟随机数被推送到列表上的测试,在后面阅读的时候很不清楚每个数字的为。

所以我的问题是,有人遇到过更整洁的方法吗?我最好用一个枚举来定义随机性的不同域(甚至是不同类的Mutators)来更好地记录模拟数的含义?

java unit-testing random
1个回答
5
投票

使用一个模拟框架,如mockito。有了它你就可以做到这一点。

// static import for Mockito.xxx needed

final Mutator mutator = mock(Mutator.class);

// Will return value1, then value2
when(mock.randomSynapseWeightChange())
    .thenReturn(value1)
    .thenReturn(value2)
    .etc().etc();

你甚至可以自己做 Answer如果你需要返回一个更 "复杂 "的数字集,而不仅仅是指定所有的数字(例如,你想循环浏览一个指定的数字列表)。

请注意,在使用 .thenReturn() 上面的例子,如果你调用该方法三次,那么返回的值将是v1、v2、v2;四次,v1、v2、v2、v2.等等。总之,在没有指定其他的情况下,以 "最后一次返回 "取胜。

然后你甚至可以检查调用的次数。

verify(mutator, times(3)).randomSynapseWeightChange();
© www.soinside.com 2019 - 2024. All rights reserved.