Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript HTML画布单元测试_Javascript_Unit Testing_Html_Canvas - Fatal编程技术网

Javascript HTML画布单元测试

Javascript HTML画布单元测试,javascript,unit-testing,html,canvas,Javascript,Unit Testing,Html,Canvas,如何对在HTML画布上绘制的Javascript进行单元测试?应该检查画布上的绘图。由于画布上绘制的“形状”和“线”不是实际对象(就像纸上的墨水),因此很难(不可能?)对其进行正常的单元测试 标准画布的最佳功能是分析像素数据(来自putImageData/getImageData,就像bedraw所说的) 现在,我还没有试过这个,但它可能更符合你的需要。蛋糕是画布的图书馆。它使用了大量putImageData/getImageData。可能有助于你在测试中所做的事情 希望这有助于回答您的问题。如

如何对在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发布了这样一个例子
  • 如果可能的话,可以使用像frabric.js这样的库,为绘图提供更高级别的抽象。“图形”是可以直接检查或转换为SVG的JS对象,SVG更易于检查和测试
  • 用于拦截画布对象的所有函数调用和属性更改。这与选项1类似
  • 使用食堂,它为您提供了一些用于大小和对齐的Jasmine自定义匹配器,以及一个函数getBBox(),可用于确定画布上绘制的内容的大小和位置

  • 我制作了非常简单的画布,并用摩卡咖啡进行了测试。我的做法与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上发布了这篇文章,我想知道你为什么写了这样的东西:)尽管如此乏味,你可以为绘图代码编写一个模拟上下文对象,并测试对上下文对象的正确调用。