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

时间:2016-01-08 15:26:42

标签: javascript jquery backbone.js qunit

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

我已经拥有了应用程序的概念验证,因此我基本上可以很好地掌握代码的外观,而无需进行测试。它看起来像是:

(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方法可以做到这一点?

2 个答案:

答案 0 :(得分:1)

因此,我找到了一种在保持生产代码清洁的同时测试私有函数的绝佳方法。我不确定你是否使用像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有一个版本,我假设任何自动构建系统都可以这样做。您甚至可以设置监视任务,以便在每次保存时运行测试。否则,您必须在部署之前手动删除导出的测试对象。<​​/ p>

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

答案 1 :(得分:0)

基本上我所做的就是避免我想要测试的库中的任何调用。所以一切都包含在一个函数中并导出。

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