如何使用Yeoman& amp ;;自动化E2E和单元测试? AngularJS?

时间:2013-05-24 14:35:23

标签: angularjs gruntjs yeoman karma-runner

我正在使用Yeoman和generator-angular来管理AngularJS应用,但我在自动化测试方面遇到了麻烦。

运行grunt test将运行一次单元测试。我可以通过改变Gruntfile.js中的karma配置块,在单元测试之后运行E2E测试,添加e2e:

karma: {
  //...
  e2e: {
    configFile: 'karma-e2e.conf.js',
    singleRun: true
  }
},

很好:现在当我输入grunt test时,所有测试都会运行。但它们只运行一次,并且有很大的开销(启动指南针,运行服务器,启动Chrome进程等)。相反,服务器和Chrome进程应该保持运行,当我保存测试时,应该重新运行测试。

我可以通过修改karma.conf.jskarma-e2e.conf.js并设置singleRun = true,然后在一个终端窗格中运行karma start,在另一个终端窗格中运行karma start karma-e2e.conf.js来实现此目的。如果业力配置中的任何端口都没有发生冲突(默认情况下它们会这样做),这是有效的。现在我绕过了Grunt而只是做了我自己的事情(这似乎有点傻,因为Grunt应该让事情变得更容易)。

无论如何,经过一些更改(修复?) - 为了简洁而没有详细说明 - 这有效但不会削减它:我现在必须运行两个不同的命令并密切关注两个不同的终端窗格。当然有更好的方法。

如何运行单个命令来观察我的测试文件并重新运行测试?

奖金问题:为什么地球上没有按原样提供此功能?这只是发电机角度开发人员没有足够时间来实现这些东西的问题吗?我问,因为我只是刚刚进入Angular / Yeoman / Karma(你可能已经注意到了),并认为自动测试E2E和单元测试对于工作流程至关重要。

4 个答案:

答案 0 :(得分:7)

正如我在你的问题评论中提到的 - PhantomJS省去了很多麻烦。除此之外,我相信你可以处理Gruntfile中的所有内容,然后继续运行grunt test来启动整个事情。

grunt-karma允许使用一些方便的附加组件完全自定义您的业力选项。

来自文档:

  

...

     

您可以直接覆盖任何配置文件的设置:

karma: {   
  unit: {
    configFile: 'karma.conf.js',
    runnerPort: 9999,
    singleRun: true,
    browsers: ['PhantomJS']   
  }
}

  

分享配置

     

如果您有多个目标,分享共同可能会有所帮助   它们之间的配置设置。 Grunt-karma支持这一点   使用options属性:

karma: {
  options: {
    configFile: 'karma.conf.js',
    runnerPort: 9999,
    browsers: ['Chrome', 'Firefox']
  },
  continuous: {
    singleRun: true
    browsers: ['PhantomJS']
  },
  dev: {
    reporters: 'dots'
  }
}

此外,您可能希望在Yeoman的generator-angular Gruntfile code中窥探,看看还有什么可用,或者至少可以模仿。

答案 1 :(得分:0)

您可以尝试此操作仅运行e2e测试

grunt karma:e2e

答案 2 :(得分:0)

在karma.conf.js文件中(约行:38),找到autoWatch = false;并将其更改为true。

现在,如果你运行grunt karma:unit,你会发现它让测试服务器继续运行,对项目文件的任何更改都会立即再次运行测试。

答案 3 :(得分:-2)

//
// test/midway/appSpec.js
//
describe("Midway: Testing Modules", function() {
  describe("App Module:", function() {

    var module;
    before(function() {
      module = angular.module("App");
    });

    it("should be registered", function() {
      expect(module).not.to.equal(null);
    });

    describe("Dependencies:", function() {

      var deps;
      var hasModule = function(m) {
        return deps.indexOf(m) >= 0;
      };
      before(function() {
        deps = module.value('appName').requires;
      });

      //you can also test the module's dependencies
      it("should have App.Controllers as a dependency", function() {
        expect(hasModule('App.Controllers')).to.equal(true);
      });

      it("should have App.Directives as a dependency", function() {
        expect(hasModule('App.Directives')).to.equal(true);
      });

      it("should have App.Filters as a dependency", function() {
        expect(hasModule('App.Filters')).to.equal(true);
      });

      it("should have App.Routes as a dependency", function() {
        expect(hasModule('App.Routes')).to.equal(true);
      });

      it("should have App.Services as a dependency", function() {
        expect(hasModule('App.Services')).to.equal(true);
      });
    });
  });
});