嘲笑随机数

spr*_*ter 4 java random unit-testing

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

这里的问题的问题中,涉及随机性的单元测试算法的最流行的答案是使用模拟.这对我来说似乎很明智,但我的问题是,是否有人对如何做到这一点有坚实的建议.

以下是我目前如何实现这一目标.我interface为我的随机生成器定义了一个(这里为了说明目的而高度简化):

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

In the main application this interface has an implementation that wraps `Random`. In my unit testing framework I use:

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

我的单元测试然后看起来像:

@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());
}
Run Code Online (Sandbox Code Playgroud)

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

所以我的问题是,是否有人遇到过这种做法更简洁的方式?我是否会更好地使用枚举来定义随机性的不同域(甚至不同类型的Mutators)来更好地记录被模拟数字的含义?

fge*_*fge 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();
Run Code Online (Sandbox Code Playgroud)

Answer如果你需要返回一组更"复杂"的数字而不仅仅指定它们(例如你想循环遍历指定数字列表),你甚至可以自己做饭.

请注意,通过.thenReturn()上面的示例,如果您调用该方法三次,则返回的值将为v1,v2,v2; 四次,v1,v2,v2,v2.等等.简而言之,当没有指定其他时,"最后一次返回"获胜.

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

verify(mutator, times(3)).randomSynapseWeightChange();
Run Code Online (Sandbox Code Playgroud)