Javascript HTML画布单元测试
如何对在HTML画布上绘制的Javascript进行单元测试?应该检查画布上的绘图。由于画布上绘制的“形状”和“线”不是实际对象(就像纸上的墨水),因此很难(不可能?)对其进行正常的单元测试 标准画布的最佳功能是分析像素数据(来自putImageData/getImageData,就像bedraw所说的) 现在,我还没有试过这个,但它可能更符合你的需要。蛋糕是画布的图书馆。它使用了大量putImageData/getImageData。可能有助于你在测试中所做的事情Javascript HTML画布单元测试,javascript,unit-testing,html,canvas,Javascript,Unit Testing,Html,Canvas,如何对在HTML画布上绘制的Javascript进行单元测试?应该检查画布上的绘图。由于画布上绘制的“形状”和“线”不是实际对象(就像纸上的墨水),因此很难(不可能?)对其进行正常的单元测试 标准画布的最佳功能是分析像素数据(来自putImageData/getImageData,就像bedraw所说的) 现在,我还没有试过这个,但它可能更符合你的需要。蛋糕是画布的图书馆。它使用了大量putImageData/getImageData。可能有助于你在测试中所做的事情 希望这有助于回答您的问题。如
希望这有助于回答您的问题。如问题注释中所述,检查某些函数是否已使用合适的参数调用非常重要。pcjuzer提出了使用代理模式。以下示例(RightJS代码)显示了一种方法:
var Context = new Class({
initialize: function($canvasElem) {
this._ctx = $canvasElem._.getContext('2d');
this._calls = []; // names/args of recorded calls
this._initMethods();
},
_initMethods: function() {
// define methods to test here
// no way to introspect so we have to do some extra work :(
var methods = {
fill: function() {
this._ctx.fill();
},
lineTo: function(x, y) {
this._ctx.lineTo(x, y);
},
moveTo: function(x, y) {
this._ctx.moveTo(x, y);
},
stroke: function() {
this._ctx.stroke();
}
// and so on
};
// attach methods to the class itself
var scope = this;
var addMethod = function(name, method) {
scope[methodName] = function() {
scope.record(name, arguments);
method.apply(scope, arguments);
};
}
for(var methodName in methods) {
var method = methods[methodName];
addMethod(methodName, method);
}
},
assign: function(k, v) {
this._ctx[k] = v;
},
record: function(methodName, args) {
this._calls.push({name: methodName, args: args});
},
getCalls: function() {
return this._calls;
}
// TODO: expand API as needed
});
// Usage
var ctx = new Context($('myCanvas'));
ctx.moveTo(34, 54);
ctx.lineTo(63, 12);
ctx.assign('strokeStyle', "#FF00FF");
ctx.stroke();
var calls = ctx.getCalls();
console.log(calls);
你可以找到一个功能演示
我使用了类似的模式来实现API中缺少的一些特性。你可能需要修改一下以适应你的目的。祝你好运 我用Jasmine和js-imagediff编写了一个单元测试canvas和其他image-y类型的示例
我发现这比确保调用模拟画布上的特定方法要好,因为不同的方法系列可能会产生相同的方法。通常,我会创建一个具有预期值的画布,或者使用已知的稳定版本的代码来测试开发版本。我最近一直在关注画布测试,现在我想到了一个页面,该页面允许将画布与画布外观的“已知良好”图像版本进行比较。这将使视觉比较快速而简单 并且可能有一个按钮,假设输出正常,它可以更新服务器上的图像版本(通过向服务器发送toDataUrl()输出)。这个新版本可以用于将来的比较 不完全是(完全)自动化的——但它确实使比较代码的输出变得容易 编辑: 现在我做了这个:
左边的图表是真实的画布,而右边是存储在数据库中的图像,它应该是什么样子(取自我知道代码正在工作时)。将有很多这样的测试来测试我的代码的所有(最终)方面。从开发人员的角度来看,画布几乎是只写的,因为一旦绘制,就很难以编程方式获得有用的东西。当然,我们可以进行逐点识别,但这太繁琐了,这样的测试很难编写和维护 最好拦截对canvas对象的调用并进行调查。以下是一些选项:
我制作了非常简单的画布,并用摩卡咖啡进行了测试。我的做法与Juho Vepsäläinen类似,但我的看起来更简单一些。我在ec2015中写的 模拟拉票课:
import ContextMock from './ContextMock.js'
export default class {
constructor (width, height)
{
this.mock = [];
this.width = width;
this.height = height;
this.context = new ContextMock(this.mock);
}
getContext (string)
{
this.mock.push('[getContext ' + string + ']')
return this.context
}
}
export default class {
constructor(mock)
{
this.mock = mock
}
beginPath()
{
this.mock.push('[beginPath]')
}
moveTo(x, y)
{
this.mock.push('[moveTo ' + x + ', ' + y + ']')
}
lineTo(x, y)
{
this.mock.push('[lineTo ' + x + ', ' + y + ']')
}
stroke()
{
this.mock.push('[stroke]')
}
}
ContextMock类:
import ContextMock from './ContextMock.js'
export default class {
constructor (width, height)
{
this.mock = [];
this.width = width;
this.height = height;
this.context = new ContextMock(this.mock);
}
getContext (string)
{
this.mock.push('[getContext ' + string + ']')
return this.context
}
}
export default class {
constructor(mock)
{
this.mock = mock
}
beginPath()
{
this.mock.push('[beginPath]')
}
moveTo(x, y)
{
this.mock.push('[moveTo ' + x + ', ' + y + ']')
}
lineTo(x, y)
{
this.mock.push('[lineTo ' + x + ', ' + y + ']')
}
stroke()
{
this.mock.push('[stroke]')
}
}
评估模拟本身功能的一些mocha测试:
describe('CanvasMock and ContextMock', ()=> {
it('should be able to return width and height', ()=> {
let canvas = new CanvasMock(500,600)
assert.equal(canvas.width, 500)
assert.equal(canvas.height, 600)
})
it('should be able to update mock for getContext', ()=> {
let canvas = new CanvasMock(500,600)
let ctx = canvas.getContext('2d')
assert.equal(canvas.mock, '[getContext 2d]')
})
})
mocha测试用于评估返回画布的函数的功能:
import Myfunction from 'MyFunction.js'
describe('MyFuntion', ()=> {
it('should be able to return correct canvas', ()=> {
let testCanvas = new CanvasMock(500,600)
let ctx = testCanvas.getContext('2d')
ctx.beginPath()
ctx.moveTo(0,0)
ctx.lineTo(8,8)
ctx.stroke()
assert.deepEqual(MyFunction(new CanvasMock(500,600), 8, 8), canvas.mock, [ '[getContext 2d]', '[beginPath]', '[moveTo 0, 0]', [lineTo 8, 8]', '[stroke]' ])
})
因此,在本例中,myfunction将传入的画布作为参数(myfunction(new CanvasMock(500600),8,8))并在其上写一行,从0,0到传入的任何参数(myfunction(new CanvasMock(500600),**8,8**),然后返回编辑过的画布
因此,当您在现实生活中使用该函数时,您可以传入实际的画布,而不是画布模拟,然后它将运行相同的方法,但执行实际的画布操作
阅读关于mock的文章你能把你的问题扩大一点吗?你到底想测试什么?您可能需要编写某种形式的验证函数来简化测试。我想测试一个Javascript图表绘制引擎。我想检查合适的线条和形状是否放置在HTML画布的正确位置。(坐标、颜色、厚度等)正常。我想你可以通过我做点什么。您可以使用该方法检查像素的颜色。如果您可以编写一些虚拟测试来确定您将需要什么样的API,这可能会有所帮助。对于我来说,检查某些函数是否已使用画布上的适当参数调用就足够了。我想到了某种代理。画布测试实用程序:嘿,我看到你在twitter上发布了这篇文章,我想知道你为什么写了这样的东西:)尽管如此乏味,你可以为绘图代码编写一个模拟上下文对象,并测试对上下文对象的正确调用。