【问题标题】:testing code transpiled for es6测试为 es6 编译的代码
【发布时间】:2015-02-27 00:40:56
【问题描述】:

我正准备使用 Qunit 为一个 Backbone 应用程序编写一些测试,该应用程序是为 ES6 编写的,并应用了 babel.js,以便它可以在现代浏览器中运行。为了确保我正确设置了 qunit 并正确指定了所有路径,我首先测试了一个用 ES5 编写的 Backbone 模型,并且一切都按预期工作。然而,我随后将bundle.js(其中包含应用了 babel.js 的 ES6 代码的结果)包含在我的tests/index.html 中,并写了

 test ( "Code transformed by babel.js contained in bundle.js can be tested", function(){
    expect(1);
    var es6model = new ES6Model();
    equal( es6model.get("defaultproperty"), "defaultstring", "defaultproperty should be defaultstring");
 })

它告诉我ES6Model 没有定义。

问题:babeljs 转换的代码是否有一些东西会使使用 Qunit 进行测试变得更具挑战性?

除了babel在文件顶部写的所有复杂的js之外,bundle.js中的代码看起来是这样的

var Model = Backbone.Model;
var View = Backbone.View;
var Collection = Backbone.Collection;
var Router = Backbone.Router;
var LocalStorage = Backbone.LocalStorage;

var ES6Model = (function (Model) {
    function ES6Model() {
        _classCallCheck(this, ES6Model);

        if (Model != null) {
            Model.apply(this, arguments);
        }
    }

    _inherits(ES6Model, Model);

    _prototypeProperties(Gopher, null, {
        defaults: {
            value: function defaults() {

                return {
                    defaultproperty: "defaultstring"

                };
            },
            writable: true,
            configurable: true
        }
    });

    return ES6Model;
})(Model);

更新

我将 babel.js 创建的所有代码包含在一个名为 bundle.js 的文件中,并将其包含在我的 index.html 中,就像我对任何其他 js 文件一样,它运行没有问题,这就是为什么我认为我可以测试它像任何其他 js 代码一样。但是,应该注意(正如评论者指出的那样)babel.js 创建的代码包含在一个模块中。这就是 bundle.js 如何从我要测试的模型开始的

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";

更新

我正在使用 browserify 将 babel 应用于我的 ES6 代码的各种文件,从而创建一个包。为了运行测试,我执行npm run test 并编译捆绑包,我尝试了这两种方法(其中一个使用modules --ignore),但它们都不起作用

“脚本”:{

    "test": "./node_modules/karma/bin/karma start --log-level debug",
    "build-js": "browserify app/app.js app/views.js app/models.js  app/d3charts.js -t babelify > app/bundle.js",
    "t-build": "browserify app/app.js app/views.js app/models.js app/d3charts.js -t [babelify --modules ignore] > app/test/test-bundle.js"
  },

(该应用程序是一个 Backbone.js 应用程序)。

这是我的业力配置文件。我没有任何进一步的配置(所以我猜我包含 karma-require 是一种浪费,但可能是必要的......)

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['qunit'],
    plugins: ['karma-qunit', 'karma-phantomjs-launcher', 'karma-requirejs'],

    files : [
      'app/test/jquery.js',     
      'app/test/d3.js',
      'app/test/json2.js',
      'app/test/underscore.js',
      'app/test/backbone.js',
      'app/backbone.localStorage.js',

      'app/test/test-bundle.js',
      'app/test/tests.js'

    ],


    reporters: ['progress'],

    // web server port
    port: 8080,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // See http://stackoverflow.com/a/27873086/1517919
    customLaunchers: {
        Chrome_sandbox: {
            base: 'Chrome',
            flags: ['--no-sandbox']
        }
    }
  });
};

【问题讨论】:

  • 可能“文件顶部的所有复杂 js”设置了一个包含 ES6Model 的模块范围。如何在普通页面中包含和调用它,这行得通吗?
  • @Bergi 哈哈。我将 babel.js 创建的所有代码包含在一个名为 bundle.js 的文件中,并像包含任何其他 js 文件一样包含它,并且它运行没有问题,这就是为什么我认为像普通测试它不会有任何问题js。但是,是的,你是对的,它似乎确实创建了一个模块范围,因为 bundle.js 像这样开始 (function e(t,n,r){function s(o,u){if(!n[o])...

标签: javascript qunit ecmascript-6 babeljs


【解决方案1】:

作为参考,他们使用 traceur 执行此操作的方法是将 traceur-runtime.js 文件编译到代码中(请参阅 https://github.com/google/traceur-compiler/issues/777 - 类似的变量未定义错误)。

例如

traceur --out out/src/yourcode.js --script lib/traceur-runtime.js --script test/yourcode.js

(见离线编译https://github.com/google/traceur-compiler/wiki/Compiling-Offline)。

【讨论】:

【解决方案2】:

在执行之前将 Babel 生成的模块导入您的测试(推荐)

您需要包含一个模块加载器(例如SystemJS)来处理导入。 Babel 的模块系统有excellent documentation

看起来像这样:

System.import( 'path/to/ES6Module' )
  .then( function( ES6Module ) {
    // … Run your tests on ES6Module here
  });

注意: System.import() 返回 Promise,因此您的测试套件需要支持异步操作。


告诉 Babel 跳过模块生成(更简单)

你可以告诉 Babel 不要使用 --modules ignore 标志将你的代码包装在一个模块中。这允许您的代码设置全局变量,立即可用于您的单元测试。全局变量为not recommended(尤其是在生产系统中),但它们更易于应用。

【讨论】:

  • 我试过--modules ignore,虽然它让我摆脱了让我发布这个问题的最初问题,但它并没有解决所有问题。例如,我的 ES6 应用程序由多个文件组成,这些文件之间的导入语句似乎没有得到尊重,即从其中一个文件导入的一些函数在测试中仍然不可见。
  • @BrainLikeADullPencil 这正是 --modules ignore 应该做的,所以最好尝试 SystemJS 来代替
  • 写完评论后,我意识到我可能没有表达清楚。我使用 browserify 将 babel 应用到我的 ES6 代码中,并将 --modules ignore 标志传递给它。这会将所有 ES6 代码放在 bundle.js 文件中。虽然你说这就是 --modules ignore “应该做的”,但我仍然可以从创建 bundle.js 文件的各种文件中看到 bundle.js 文件中的函数,所以要么 --modules ignore 没有这样做东西,或者我不明白你的意思。不管怎样,我写测试的时候,即使函数在bundle.js里面,测试代码也看不到
  • 啊,这有区别……您可以分享一下您的 browserify 配置和您正在使用的测试套件,而不是解释您的设置吗?
  • 我使用来自package.json 的行更新了 OP,我使用这些行来创建包并运行测试。还添加了业力配置文件。感谢您提供的任何帮助。
猜你喜欢
  • 2018-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
相关资源
最近更新 更多