我试图创建一个不符合标准" todo"的react / redux应用程序。所以我和2048一起去了,这是一个相当有趣的游戏,我可以随便摆弄。
我已经完成了游戏"工作" (游戏按照规则进行游戏),现在我想要追溯性地添加一些测试用例,以确保我不会破坏任何重要的事情(并且,y'知道,练习)
我为电路板设置了一个缩减器,用于监听不同的操作:
const Board = (state = 0, action) => {
if(state === 0){
return createBoard();
}
switch (action.type) {
case 'MOVE_UP':
return move(state, 0);
case 'MOVE_RIGHT':
return move(state, 1);
case 'MOVE_DOWN':
return move(state, 2);
case 'MOVE_LEFT':
return move(state, 3);
case 'NEW_GAME':
return createBoard();
default:
return state;
}
}
然而,移动(板,方向)功能完成了大部分繁重工作,并且是出现问题的地方:
function move(board, direction){
//0: up, 1: right, 2: down, 3: left
var b;
switch(direction){
case 0:
b = mergeBoardUp(board);
break;
case 1:
b = mergeBoardRight(board);
break;
case 2:
b = mergeBoardDown(board);
break;
case 3:
b = mergeBoardLeft(board);
break;
default:
b = board.map(x => x);
}
if(distinctBoard(board, b)){
b = addNewTile(b);
}
return b;
}
我的理解是减速器应该进行黑盒测试(不要试图拉出并测试" mergeBoardUp"功能,在使用后测试状态)。由于游戏的性质,只要播放有效的移动(if(distinctBoard){addNewTile}
),就会添加新的图块。
我已经有一套非常好的测试用例,我想在测试电路板轮换和合并方面实施,但是我无法找到一种方法来解决随机问题。 #34;瓷砖放置。
示例测试用例供参考:
it("MoveUp - simple", () => {
var input = [[2,0,0,0],
[2,4,8,16],
[2,4,0,16],
[2,4,8,0]];
var inputHistory = {
past: [],
present: input,
future: []
};
var expected = [[4,8,16,32],
[4,4,0,0],
[0,0,0,0],
[0,0,0,0]];
var rotatedLeft = Board(inputHistory, MovementButtons.moveUp()).present;
expect(rotatedLeft).toBe(expected);
})
上述操作失败,因为在有效移动之后,新的磁贴会随机放入数组中,从而导致"期望"数组总是偏离一个值。
在这种情况下测试的适当方法是什么? 我的直觉是大吼大叫把我想要测试的函数分成一个实用程序文件(并从中测试导出的函数),但这似乎是测试reducers的反模式。
答案 0 :(得分:3)
这里的真正问题是随机性不应该在reducer中发生 。减速器应该是纯粹的功能",没有副作用。 不是纯净的减速器代码仍将运行,但时间旅行调试将无法按预期运行,并且正如您所发现的那样,测试变得困难。
有几种方法可以考虑重组事情。您可以将大部分逻辑放入动作创建器中,并让reducer逻辑根据需要简单地将数据合并到位。另一种方法可能是让动作创建者生成所需的随机性,并将其包含在动作中。这样减速器本身就保持纯净,确定性和可测试性。
答案 1 :(得分:0)
我会再问,我想测试什么?看起来您可以测试两种不同的功能:MoveUp&merge和MoveUp的随机新行。
您似乎可以通过以下方式正确地对MoveUp的合并功能进行单元测试:
expect(rotatedLeft.slice(0,3)).toEqual(expected.slice(0,3));
通过正确捕获前三行的合并,我说这足以作为MoveUp合并功能的单元测试。
然后单独地,您可以通过检查最后一行中的每个值是否属于可能的随机值集来测试最后一行是否是随机的。
for (var i = 0; i < rotatedLeft[3].length; i += 1) {
expect([0, 2, 4]).toContain(rotatedLeft[3][i]);
}