单元测试带有页面重新加载和iframe的JS应用程序

时间:2013-12-31 12:49:38

标签: javascript unit-testing iframe jasmine funcunit

我有一个应用程序页面重新加载/导航和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)似乎专注于高级抽象,例如“点击元素”,“检查元素的价值”等,而不是提供挖掘的能力代码执行。

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

3 个答案:

答案 0 :(得分:5)

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服务器等服务一起针对真实浏览器运行功能测试。

答案 1 :(得分:3)

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

另一方面,您展示的单元测试类型是通过模拟所有交互部分并单独测试单元来测试程序的各个单元,如控制器。

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

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

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

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

答案 2 :(得分: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()
      })
    })
})