组织一个中等大小的javascript客户端应用程序的代码进行测试

Organizing code of a midly sized javascript client side app for testing

本文关键字:客户端 javascript 应用程序 代码 测试 一个      更新时间:2023-09-26

我正在使用主干网及其好友jquery和下划线构建一个中等大小的应用程序。我的计划是使用QuitJS来创建单元测试。

我已经有了这个应用程序的概念证明,所以我基本上很好地掌握了代码应该是什么样子,而不需要测试它

(function() {
  // prepare some model
  var Query = BackboneModel.extend({});
  query = new Query();
  // register some events
  $('body.something').click(function() {
    query.set('key', 'value');
    # ...
  });
  // create some backbone view
  var QueryView = Backbone.View.extend({...})
  // init backbone view
  query.view = new QueryView();
  // add some plumbing here ...
  // and so on... 
})();

否则说:

  • 我将模块封装在函数中以避免污染
  • 类声明和类使用是交错的
  • 事件注册与代码的其余部分交错
  • 模块的全局变量在模块内部重复使用

现在我需要测试一下。问题是,我认为主要是关于事件注册和管道。

我的计划是将代码封装在函数中,并导出我想要测试的每个函数和对象。代码将如下所示:

var app = (function() {
  var app = {}
  // prepare some model
  var Query = BackboneModel.extend({});
  app.query = new Query();
  // register some events
  app.registerEvent = function() {
    $('body.something').click(function() {
      query.set('key', 'value');
      # ...
    });
  };
  app.registerEvent();  // XXX: call immediatly
  // create some backbone view
  app.QueryView = Backbone.View.extend({...})
  // init backbone view
  app.query.view = new QueryView();
  // add some plumbing here ...
  // wrapped in function with correct arguments and call it immediatly
  // and so on... 
  // ...
  return app;
})();

这是我第一次需要用javascript为这种应用程序编写测试,所以我想知道我使代码可测试的方法是正确的还是可以改进的。例如,在我看来,将事件的注册封装在没有参数的函数中并立即调用它们是愚蠢的。

有没有javascript方法可以做到这一点?

因此,我找到了一种极好的方法来测试私有函数,同时保持生产代码的整洁。我不确定你是否使用任何像Grunt或Gulp这样的构建系统,但如果你对它持开放态度,你可以做这样的事情:

//has a dependency of 'test' causing it to run testing suite first
gulp.task('js', ['test'], function() {
return gulp.src(source)
    .pipe(plumber())
    //create sourcemaps so console errors point to original file
    .pipe(sourcemaps.init())
    //strip out any code between comments
    .pipe(stripCode({
        start_comment: 'start-test',
        end_comment: 'end-test'
    }))
    //combine all separatefiles into one
    .pipe(concatenate('mimic.min.js'))
    //minify and mangle
    .pipe(uglify())
    .pipe(sourcemaps.write('maps'))
    .pipe(gulp.dest('dist/js'));
});

文件可能看起来像:

var app = (function () {
    function somePrivateFunction () {}
    function someotherPrivateFunction () {}
    var app = {
        publicFunction: function(){}
        publicVar: publicVar
    }
    /* start-test */
    app.test = {
        testableFunction: somePrivateFunction
    }
    /* end-test */
}());

测试运行后,测试注释之间的所有内容都会被剥离,因此生产代码是干净的。Grunt有一个版本,我想任何自动化构建系统都可以做到这一点。您甚至可以设置一个监视任务,以便它在每次保存时运行测试。否则,您将不得不在部署之前手动删除导出的测试对象。

在Backbone的情况下,只需将测试对象附加到模块并在测试中引用该对象。或者,如果您真的想将其分离,请在全局范围内设置对象。window.testObject = { //list of objects and methods to test... };,并在部署前将该代码剥离。

基本上,我所做的是避免在我想要测试的库中进行任何调用。因此,所有内容都封装在一个函数中并导出。

然后我有另外两个文件,一个是main.js,我在那里做管道,应该使用带有selenium的集成测试和tests.js进行单元测试。