【问题标题】:unit testing JS app with page reloads and iframes使用页面重新加载和 iframe 对 JS 应用程序进行单元测试
【发布时间】:2013-12-31 12:49:37
【问题描述】:

我有一个应用程序,其中页面重新加载/导航和 iframe 至关重要,而这些部分似乎很难用单元测试覆盖。

我希望能够编写 smt。像这样:

it('should fire appropriate callbacks on start and page reload', function() {
  app.start();
  expect(app.onStart).toHaveBeenCalled();
  page.reload();
  expect(app.onRestart).toHaveBeenCalled();
}

it('should know whether it runs in iframe or not', function() {
  expect(app.isInIframe()).toBe(false);
  iframe = createTestIframe();
  expect(iframe.getApp().isInIframe()).toBe(true);
}

我所知道的单元测试框架(mocha、Jasmine、QUnit)都是为了在一个页面上、在顶级上下文中完成整个测试套件而设计的。

另一方面,功能测试框架(FuncUnit、TestCafé、Selenium WebDriver)似乎专注于高级抽象,例如“单击元素”、“检查元素的值”等,无法深入挖掘代码执行。

免责声明:我对一般测试比较陌生,所以也许我应该完全从不同的角度看待这个问题。

【问题讨论】:

    标签: javascript unit-testing iframe jasmine funcunit


    【解决方案1】:

    Intern 正是为了在这些情况下启用这些类型的功能测试而设计的,并且实际上是由于您描述的现有 JS 测试框架无法启用这些类型的交互的问题而创建的。它包括一个功能测试接口,可以像这样工作,假设 app 在 Node.js 方面,你会做这样的事情:

    define([ 'intern!bdd', 'intern/chai!expect', 'my/app' ], function (bdd, expect, app) {
       var it = bdd.it;
    
       it('should fire appropriate callbacks on start and page reload', function() {
         app.start();
         return this.remote.get('http://path/to/server')
           .then(function () {
             expect(app.onStart).toHaveBeenCalled();
           })
           .refresh()
           .then(function () {
             expect(app.onRestart).toHaveBeenCalled();
           });
       });
    
       // ...etc.
    });
    

    Intern tutorial 更好地概述了单元测试和功能测试之间的区别以及如何使用这两者。与 CasperJS 之类的其他建议不同,它实际上会使用标准 WebDriver API 以及诸如 Sauce Labs 或您自己的 Selenium 服务器之类的服务,针对真实浏览器运行您的功能测试。

    【讨论】:

    • 谢谢!这看起来正是我一直在寻找的。有了 grunt 和 WebDriver 支持——很好吃!想知道它是如何一直受到我的关注直到今天 :)
    【解决方案2】:

    您描述的测试似乎是完整的集成测试,而不是单元测试(刷新/iframe)。

    另一方面,您展示的那种单元测试旨在通过​​模拟所有交互部分并单独测试单元来测试程序的单独单元,例如控制器。

    对于您要执行的测试类型(包括 iframes/refreshes),最好使用集成测试工具,例如 Selenium IDE

    此工具有一个宏记录器,可记录您在测试中的浏览器操作,并允许重放操作并添加断言以检查测试结果。看看这个demo video,看看它使用起来有多简单。

    这种集成测试补充但不能替代您展示的单元测试类型。

    集成测试的数量要比单元测试少得多,请参阅test pyramid,了解有关测试和平衡单元测试和集成测试数量的一些最佳实践。

    【讨论】:

    • 我知道 Selenium,我们将它用于高级集成测试,但它不允许我控制低级实体,如模块、控制器等,无论你如何命名它们。看起来我必须坚持对我想要运行的单元测试进行模拟/存根......
    【解决方案3】:

    你可以试试CasperJS。它在 PhantomJS 中运行功能测试,您可以在测试页面中评估任意代码。对于您的情况,您应该能够执行以下操作:

    casper.test.begin('iframe', 1, function (test) {
      casper
        .start('your.page.url')
        .thenEvaluate(function () {
          window.iframe = createTestIframe()
        })
        .then(function () {
          test.assertEval(function () {
            return iframe.getApp().isInIframe()
          })
        })
    })
    

    【讨论】:

    • 感谢您的建议!但不幸的是,对于 CasperJS,我们只能在 PhantomJS (Webkit) 和 SlimerJS (Gecko) 中进行测试。我需要能够在包括 IE 在内的真实浏览器中运行测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 2012-03-21
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    相关资源
    最近更新 更多