茉莉花 + JSTestDriver + 覆盖率 + RequireJS

7

哇,真是一团糟。这就是情景。

  • Backbone driven JS app.
  • RequireJS for AMD functionality, initialized like this:

    <script data-main="js/main" src="js/require.js" type="text/javascript"></script>
    

    then inside main.js the following config code:

    require.config(
    {
        paths:
        {
            ... : ...
        }
    });
    

    Each Backbone View/Model/Router is a "define(...)" module, and "require("theOneRouter", ...)" is called once in main.js.

  • r.js used as optimizer with Uglify/Closure. One 'compiled' main.js is created in a ./release subfolder which I pick dynamically within my .net framework.

  • Took quite a while to get the Backbone + Require.JS to work, but works great now!

  • Then slapping Jasmine on top of that also took a little custom work, but it worked just fine. I had to load require.js from my SpecRunner.html, define each test module as an AMD using require's define(...) call, and I instantiate & run Jasmine once from a call to require's require(...) call once in the SpecRunner.html:

    require(
    [
    //"test/specs/testSpec1",
    "test/specs/views"
    ],
    function ()
    {
        jasmine.getEnv().updateInterval = 1000;
        var reporter = new jasmine.TrivialReporter();
        jasmine.getEnv().addReporter(reporter);
        ....
        ....
    });
    

    this too works great. Tests load & run, no issues. Require takes care of everything.

现在,我希望有一个像JSTestDriver这样的框架作为我的测试运行器。我选择JSTD是因为它简单易用,能够在远程浏览器上进行测试,并且支持代码覆盖率,但我仍然愿意听取其他建议。
JSTestDriver本身运行良好,唯一的问题是如何同时运行JSTD + Jasmine + RequireJS组合。最大的问题是,如果我告诉配置文件中的JSTD有一个Jasmine/Require测试模块需要加载,我会得到以下错误:

http://requirejs.org/docs/errors.html#mismatch

如果我使用r.js将所有代码优化为一个main.js,合并可以工作,包括覆盖率,但覆盖率仅在一个巨大的文件中收集,难以分析。更何况,对于50k行代码的js文件进行测试很耗时,并通过JSTD运行。
我尝试创建一个类似fixture的js文件,加载所有的Jasmine测试模块和代码模块,但我一直遇到上述“不匹配”错误,而且如果我没有告诉JSTD每个模块(通过加载真正的加载html/js fixture)它们将不会获得代码覆盖率测量。
有人已经让这个特定的组合工作了吗?也许我要求太多了...
4个回答

4
解决方案与devadvocate所提到的完全一致。因为JsTestDriver和Require.js竞争管理文件/依赖项的方式,当您尝试100%按照Require.js的方式(使用匿名模块和define)时,JsTestDriver会出现问题。相反,您必须命名模块并使用require([...], function(...) {...而不是define([...]. 我写了一篇文章,展示了如何将QUnit、Requirejs和代码覆盖率与JSTD集成:js-test-driver+qunit+coverage+requirejs. 我在示例中使用了QUnit,但您可以轻松地将其替换为Jasmine。在尝试解决此问题时,我考虑过仅使用PhantomJS,但对于我们的用户群体来说,跨浏览器测试非常重要,包括IE7、IE8、IE9等,因此单个WebKit不足以满足需求。 JsTestDriver非常有用,但恐怕文档质量不佳会让开发人员望而却步。很快我将在GitHub上发布我的示例代码。希望这可以帮助到您。

感谢您的输入和好评。是的,您提到的观点是正确的,我已经尝试手动命名我的模块并使用 require 调用而不是 define(),但这不是可行的解决方案:即使自动化,每次测试运行之前都需要执行大量额外的工作,这会影响开发期间快速运行测试的效率,因此我希望避免这种情况。 - Bernardo
1
现在我有一个经过修补的jsTestDriver.jar版本,可以通过正则表达式排除文件。它还允许从“serve”部分加载JavaScript文件。提供JavaScript源文件意味着当浏览器页面加载时,它们不会自动执行。相反,当浏览器执行require.js时,require能够从serve部分拉取文件。这样,模块可以是匿名的,没有任何问题。请参见Backbone-Testing - jdobry

2

我无法让它正常工作,最终使用 PhantomJS 运行我的 Jasmine 测试。http://phantomjs.org/


我考虑过PhantomJS,但JSTD的重点是运行跨平台单元测试,而PhantomJS不支持无头Webkit。我想这就引出了一个问题,是否有必要进行跨平台单元测试:我应该在无头环境中运行单元测试,并且只专注于在类似Selenium的跨浏览器环境中运行集成/验收测试吗? - Bernardo
我为跨浏览器运行单元测试构建了自己的解决方案。我没有自动化这个过程,但你可以很容易地扩展这个解决方案来实现自动化。这是我的博客文章链接 --> link - Blake B
经过几周的实验,我仍然坚信单元测试应该在浏览器环境中运行,而不是无头模式。因此,我一直在尝试使用Selenium和托管的SauceLabs解决方案,并且到目前为止,大部分都可以正常工作。我唯一的问题是代码覆盖率:JSTD具有良好的平滑集成覆盖工具和报告,但我似乎找不到一个类似智能的仪器来适用于自定义环境。 - Bernardo

2
你是否尝试过为测试模块命名并在测试中使用require而非define? https://github.com/podefr/jasmine-reqjs-jstd 编辑:
我刚发布了一个开源工具包,希望能像帮助我一样帮助其他人。它是许多开源工具的组合,可以让你立即拥有一个可用的requirejs骨架应用。
它提供单个命令来运行:开发Web服务器、Jasmine单浏览器测试运行程序、Jasmine JS测试驱动程序多浏览器测试运行程序以及JavaScript和CSS的连接/最小化。它还输出未最小化版本的应用程序以进行生产调试,预编译你的handlebar模板,并支持国际化。 无需设置,它只需正常工作。
它还支持未命名的测试模块。 http://github.com/davidjnelson/agilejs

是的,我看过那个项目并且成功地使用过它,但是它太繁琐了。在一个有许多模块需要许多其他模块的大型项目中,我必须建立一个系统来自动命名所有测试模块。在我看来,这是一个很大的痛点。我发现使用Selenium和Node覆盖率更加简洁的解决方案... - Bernardo
我已经用我的新agilejs工具包(http://github.com/davidjnelson/agilejs)解决了这个问题。 - davidjnelson

0

请查看此仓库(Bredele appolo),它是一个在使用 require.js 和 JsTestDriver 加载匿名模块的环境下运行 Jasmine BDD 规范的工具。

如果您正在开发非匿名模块,我还建议使用 podefr 解决方案。

Olivier


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接