如何测试javascript交互,例如在html5画布中使用鼠标绘图

时间:2012-03-20 18:21:43

标签: jquery html5 canvas tdd jasmine

我熟悉测试对象状态,例如在rails模型上的ruby中使用rspec。例如:对于此先前状态并接收此调用,此对象应满足此期望。

但是如果我想在jquery插件上做一些TDD来绘制html5画布中的线条呢?我该怎么测试呢?鉴于用户已单击画布并移动指针,则应在画布上绘制一条线。这不像我可以像使用茉莉花那样模拟用户活动吗?这是否超出了TDD的范围,只能进行手动测试?

2 个答案:

答案 0 :(得分:4)

很难知道在哪里停止测试,应该测试什么以及如何测试。 一般来说,当我必须处理与我正在开发的东西,图书馆,网络服务,ajax调用,外部服务器,画布的外部接口时,我会开始考虑如何嘲笑它。

我对画布不太熟悉。我会用以下任何一种方式来解决这个问题:

1)如果你只想确保你的代码对画布有用,那么直接在它上面使用间谍就很简单了。间谍是非常强大的工具,了解它们并使用它们。例如,如果您想确保更新画布路径,则可以执行

var spy = spyOn(canvas, 'moveTo').andCallFake(function (x, y) {
  expect(x).toEqual(10.0);
  expect(y).toEqual(20.0);
});

//Do something through your api that would call canvas.moveTo
...
expect(spy).toHaveBeenCalled();

当然,你可以窥探任何其他画布方法。

2)如果您需要进行大量交互的测试和/或您发现自己一次又一次地为不同的测试编写相同的间谍,那么您可能会更好地使用模拟对象。小心:不要重写你正在嘲笑的库!保持简单,只模拟您需要的东西,随时添加。另外,看一下可能会帮助你或者给你想法的可用的模拟库。很多茉莉花人正在使用sinon。就个人而言,我坚持使用裸茉莉,并在需要时依靠自己的嘲笑。

是的,所以让我试着想出一些东西;)对于画布,我希望一个模拟对象会说出你需要的基本方法,beginPathmoveTo,{{1无论如何......你可以做到这一点,它不是绘制到画布,而是将点附加到表示路径的数组。然后,您的测试将与您的代码进行多次交互,最后您可以从模拟中获取路径并为其提供期望。

答案 1 :(得分:1)

您可以并且应该通过在每次调用鼠标或触摸事件时调用某些函数或状态来模拟用户活动。这种输入规范化使您可以非常轻松地模拟输入。

例如,您可以编写一个画布应用程序,从鼠标向下拖动到鼠标向上。我们可以这样写:

var can = document.getElementById('canvas1'); var ctx = can.getContext('2d');

can.addEventListener('mousedown', function(e) {
    var mouse = getMouse(e, can);
    doMouseDown(ctx, mouse.x, mouse.y);
}, false);

can.addEventListener('mouseup', function(e) {
    var mouse = getMouse(e, can);
    doMouseUp(ctx, mouse.x, mouse.y);
}, false);


function doMouseDown(ctx, x, y) {
    ctx.beginPath();
    ctx.moveTo(x, y);
}

function doMouseUp(ctx, x, y) {
    ctx.lineTo(x, y);
    ctx.stroke();
}

现在,如果您想模拟用户将鼠标放在某个地方以及其他地方,那么您需要编写的是:

// simulate the mouse doing these actions!
doMouseDown(ctx, 50, 50);
doMouseUp(ctx, 200, 120);​

够容易!

这不是解决此类问题的最佳方式,但它可以为您提供这个想法。我会为每个画布制作一种状态对象/类,但这仅仅是组织问题。

然后测试变得容易,因为用户使用鼠标或触摸板进行的任何操作都可以在代码中进行测试。实际上,您的鼠标按下代码和触摸启动代码现在都可以被认为与您的应用程序等效,因为它们都会简单地调用doMouseDown / Up。作为一个原则问题,将执行逻辑与原始输入分开总是好的。

以下是适合您的完整工作示例:http://jsfiddle.net/CU72J/