【问题标题】:How can I automate both E2E and unit tests with Yeoman & AngularJS?如何使用 Yeoman 和 AngularJS 自动化 E2E 和单元测试?
【发布时间】:2013-05-20 04:55:50
【问题描述】:

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

运行grunt test 将运行一次单元测试。我可以通过更改 Gruntfile.js 中的业力配置块,添加 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 来实现这一点。如果 karma 配置中的端口没有冲突(默认情况下会发生冲突),则此方法有效。现在我绕过 Grunt,只做我自己的事情(这似乎有点傻,因为 Grunt 应该让事情变得更容易)。

无论如何,在进行了一些更改(修复?)之后——为了简洁起见,没有详细说明——这可行,但不会削减它:我现在必须运行两个不同的命令并密切关注两个不同的终端窗格。肯定有更好的方法。

如何运行单个命令来查看我的测试文件并适当地重新运行测试?

额外问题:为什么没有按原样提供此功能?这只是 generator-angular 的开发人员没有足够的时间来实现这些东西的问题吗?我之所以这么问,是因为我才刚刚接触到 Angular/Yeoman/Karma(您可能已经注意到了),并且觉得 E2E 和单元测试的自动化测试对于工作流程至关重要。

【问题讨论】:

  • 迄今为止我想出的最干净的解决方案是使用Node Foreman 在同一个窗口中启动两个业力实例。 Year of Moo 使用此方法。我觉得最好的解决方案可能涉及这样的事情,但我仍然对为什么角度生成器不包含它感到困惑。
  • 这两种类型的测试都提供了一个 html 报告器,对吗?假设这是真的,您可以创建一个简单的网页,其中包含两个 iframe,其中包含每个测试报告。然后批处理程序可以运行这两种类型的测试,启动浏览器,并将其指向您创建的网页。这两种类型的测试使用完全不同的测试运行器(jasmine 和 angular-scenario),因此 karma 不能同时运行开箱即用是有道理的。不过我同意,应该提供该功能。
  • @robbymurphy 这是个好主意!不过,我不确定我将如何实现这一点,以及它是否真的可能(尽管听起来应该如此)。此外,node foreman 是一个相当快速的解决方案,所以我不确定是否值得额外配置。
  • 我建议尝试 PhantomJS 而不是 Chrome,这样可以节省打开窗口。

标签: angularjs gruntjs yeoman karma-runner


【解决方案1】:

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

现在,如果您运行 grunt karma:unit,您会发现它使测试服务器保持运行,并且对项目文件的任何更改都会立即再次运行测试。

【讨论】:

    【解决方案2】:

    你可以试试这个只运行 e2e 测试

    grunt karma:e2e
    

    【讨论】:

    • 这给了我这个错误信息 [PhantomJS 1.9.2 (Mac OS X)]: Connected on socket iFpamoP1eO3ongWLY4Xi PhantomJS 1.9.2 (Mac OS X): Executed 0 of 0 ERROR (0.356 secs / 0 秒)
    【解决方案3】:

    正如我在对您的问题的评论中提到的 - PhantomJS 节省了很多麻烦。除此之外,我相信您可以在 Gruntfile 中处理所有事情,只需继续运行 grunt test 即可开始整个事情。

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

    来自文档:

    ....

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

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

    共享配置

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

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

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

    【讨论】:

    • 我已经离开了 Angular,所以我无法确认这是否解决了问题。看起来共享配置是要走的路,所以我会接受。
    • 如果您同时拥有 e2e 和单元测试并希望它们具有不同的 dev 和 build 配置,配置会是什么样子?例如在 dev 中同时使用 e2e 和 unit 时,您想使用 Chrome 并让 karma 监听文件更改而无需重新启动浏览器,并且在构建时您想使用 PhantomJS 和 singleRun:true
    【解决方案4】:
    //
    // 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);
          });
        });
      });
    });
    

    【讨论】:

    • 中途测试不是这里的问题,尽管这意味着要运行另一个测试套件。
    猜你喜欢
    • 2016-02-17
    • 2014-01-11
    • 1970-01-01
    • 2021-09-07
    • 2015-07-13
    • 1970-01-01
    • 2021-09-02
    • 2011-01-31
    • 1970-01-01
    相关资源
    最近更新 更多