有没有办法加速AngularJS量角器测试?

时间:2021-11-29 02:44:04

I have created tests for my application. Everything works but it runs slow and even though only 1/3 of the application is tested it still takes around ten minutes for protrator to create the test data, fill out the fields, click the submit button etc.

我已经为我的应用程序创建了测试。一切正常,但运行缓慢,即使只有1/3的应用程序经过测试,仍然需要大约十分钟才能让protrator创建测试数据,填写字段,点击提交按钮等。

I am using Google Crome for the testing. It seems slow as I watch protractor fill out the fields one by one.

我正在使用Google Crome进行测试。当我看着量角器逐一填写字段时,它似乎很慢。

Here's an example of my test suite:

这是我的测试套件的一个例子:

suites: {
    login: ['Login/test.js'],            
    homePage: ['Home/test.js'],          
    adminPage: ['Admin/Home/test.js'],
    adminObjective: ['Admin/Objective/test.js'],
    adminObjDetail: ['Admin/ObjectiveDetail/test.js'],
    adminTopic: ['Admin/Topic/test.js'],
    adminTest: ['Admin/Test/test.js'],
    adminUser: ['Admin/User/test.js'],
    adminRole: ['Admin/Role/test.js']
},

This is one test group:

这是一个测试组:

    login: ['Login/test.js'],            
    homePage: ['Home/test.js'],          
    adminUser: ['Admin/User/test.js'],
    adminRole: ['Admin/Role/test.js']

This is another test group:

这是另一个测试组:

    adminPage: ['Admin/Home/test.js'],
    adminObjective: ['Admin/Objective/test.js'],
    adminObjDetail: ['Admin/ObjectiveDetail/test.js'],
    adminTopic: ['Admin/Topic/test.js'],
    adminTest: ['Admin/Test/test.js'],

The two groups can run independently but they must run in the order I have above. After the answers I did read about sharing but I am not sure if this helps my situation as my tests need to be run in order. Ideally I would like to have one set of tests run in one browser and the other set in another browser.

这两个组可以独立运行,但它们必须按照我上面的顺序运行。在答案之后,我确实读到了关于共享但我不确定这是否有助于我的情况,因为我的测试需要按顺序运行。理想情况下,我希望在一个浏览器中运行一组测试,而在另一个浏览器中设置另一组测试。

I read about headless browsers such as PhantomJS. Does anyone have experience with these being faster? Any advice on how I could do this would be much appreciated.

我读到了像PhantomJS这样的无头浏览器。有没有人有这些更快的经验?关于如何做到这一点的任何建议将不胜感激。

7 个解决方案

#1


10  

We currently use "shardTestFiles: true" which runs our tests in parallel, this could help if you have multiple tests.

我们目前使用“shardTestFiles:true”并行运行我们的测试,如果您有多个测试,这可能会有所帮助。

I'm not sure what you are testing here, whether its the data creation or the end result. If the latter, you may want to consider mocking the data creation instead or bypassing the UI some other way.

我不确定你在这里测试什么,无论是数据创建还是最终结果。如果是后者,您可能需要考虑模拟数据创建,或者以其他方式绕过UI。

#2


7  

Injecting in Data

One thing that you can do that will give you a major boost in performance is to not double test. What I mean by this is that you end up filling in dummy data a number of times to get to a step. Its also one of the major reasons that people need tests to run in a certain order (to speed up data entry).

你可以做的一件事就是给你带来性能上的一个重大提升,就是不要加倍测试。我的意思是你最终会多次填充虚拟数据以达到一个步骤。它也是人们需要测试以某种顺序运行(加速数据输入)的主要原因之一。

An example of this is if you want to test filtering on a grid (data-table). Filling in data is not part of this action. Its just an annoying thing that you have to do to get to testing the filtering. By calling a service to add the data you can bypass the UI and seleniums general slowness (Id also recommend this on the server side by injecting values directly into the DB using migrations).

例如,如果要在网格(数据表)上测试过滤。填写数据不是此操作的一部分。它只是一个烦人的事情,你必须做到测试过滤。通过调用服务来添加数据,您可以绕过UI和selenium一般的缓慢(Id也建议在服务器端通过使用迁移将值直接注入数据库)。

A nice way to do this is to add a helper to your pageobject as follows:

一个很好的方法是在页面对象中添加一个帮助程序,如下所示:

module.exports = {
    projects: {
        create: function(data) {
            return browser.executeAsyncScript(function(data, callback) {
                var api = angular.injector(['ProtractorProjectsApp']).get('apiService');
                api.project.save(data, function(newItem) {
                    callback(newItem._id);
                })
            }, data);
        }
    }
};

The code in this isnt the cleanest but you get the general gist of it. Another alternative is to replace the module with a double or mock using [Protractor#addMockModule][1]. You need to add this code before you call Protractor#get(). It will load after your application services overriding if it has the same name as an existing service.

这里的代码不是最干净的,但你得到了它的一般要点。另一种方法是使用[Protractor#addMockModule] [1]用double或mock替换模块。在调用Protractor#get()之前,需要添加此代码。如果它与现有服务具有相同的名称,它将在应用程序服务覆盖后加载。

You can use it as follows :

您可以按如下方式使用它:

var dataUtilMockModule = function () {
     // Create a new module which depends on your data creation utilities
    var utilModule = angular.module('dataUtil', ['platform']);
    // Create a new service in the module that creates a new entity
    utilModule.service('EntityCreation', ['EntityDataService', '$q', function (EntityDataService, $q) {

        /**
         * Returns a promise which is resolved/rejected according to entity creation success
         * @returns {*}
         */
        this.createEntity = function (details,type) {
            // This is your business logic for creating entities
            var entity = EntityDataService.Entity(details).ofType(type);
            var promise = entity.save();
            return promise;
        };
    }]);
};

browser.addMockModule('dataUtil', dataUtilMockModule);

Either of these methods should give you a significant speedup in your testing.

这些方法中的任何一种都可以为您的测试带来显着的加速。

Sharding Tests

Sharding the tests means splitting up the suites and running them in parallel. To do this is quite simple in protractor. Adding the shardTestFiles and maxInstences to your capabilities config should allow you to (in this case) run at most two test in parrallel. Increase the maxInstences to increase the number of tests run. Note : be careful not to set the number too high. Browsers may require multiple threads and there is also an initialisation cost in opening new windows.

对测试进行分片意味着拆分套件并将它们并行运行。在量角器中这样做非常简单。将shardTestFiles和maxInstences添加到您的功能配置应该允许您(在这种情况下)以并行方式运行最多两次测试。增加maxInstences以增加运行的测试次数。注意:注意不要将数字设置得太高。浏览器可能需要多个线程,并且在打开新窗口时也存在初始化成本。

capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 2
},

Setting up PhantomJS (from protractor docs)

Note: We recommend against using PhantomJS for tests with Protractor. There are many reported issues with PhantomJS crashing and behaving differently from real browsers.

注意:我们建议不要使用PhantomJS进行Protractor测试。有许多报道的问题与PhantomJS崩溃并且与真实浏览器的行为不同。

In order to test locally with PhantomJS, you'll need to either have it installed globally, or relative to your project. For global install see the PhantomJS download page (http://phantomjs.org/download.html). For local install run: npm install phantomjs.

要使用PhantomJS进行本地测试,您需要全局安装或相对于项目安装。有关全局安装,请参阅PhantomJS下载页面(http://phantomjs.org/download.html)。对于本地安装运行:npm install phantomjs。

Add phantomjs to the driver capabilities, and include a path to the binary if using local installation:

将phantomjs添加到驱动程序功能中,如果使用本地安装,则包含二进制文件的路径:

capabilities: {
  'browserName': 'phantomjs',

  /* 
   * Can be used to specify the phantomjs binary path.
   * This can generally be ommitted if you installed phantomjs globally.
   */
  'phantomjs.binary.path': require('phantomjs').path,

  /*
   * Command line args to pass to ghostdriver, phantomjs's browser driver.
   * See https://github.com/detro/ghostdriver#faq
   */
  'phantomjs.ghostdriver.cli.args': ['--loglevel=DEBUG']
}

#3


3  

Another speed tip I've found is that for every test I was logging in and logging out after the test is done. Now I check if I'm already logged in with the following in my helper method;

我发现的另一个速度提示是,每次测试我都会登录并在测试完成后退出。现在我检查我是否已经在我的帮助方法中使用以下内容登录;

  # Login to the system and make sure we are logged in.
  login: ->
    browser.get("/login")
    element(By.id("username")).isPresent().then((logged_in) ->
      if logged_in == false
        element(By.id("staff_username")).sendKeys("admin")
        element(By.id("staff_password")).sendKeys("password")
        element(By.id("login")).click()
    )

#4


2  

I'm using grunt-protractor-runner v0.2.4 which uses protractor ">=0.14.0-0 <1.0.0". This version is 2 or 3 times faster than the latest one (grunt-protractor-runner@1.1.4 depending on protractor@^1.0.0)

我正在使用grunt-protractor-runner v0.2.4,它使用量角器“> = 0.14.0-0 <1.0.0”。这个版本比最新版本快2到3倍(grunt-protractor-runner@1.1.4取决于protractor@^1.0.0)

So I suggest you to give a try and test a previous version of protractor

因此,我建议您尝试并测试以前版本的量角器

Hope this helps

希望这可以帮助

#5


2  

Along with the great tips found above I would recommend disabling Angular/CSS Animations to help speed everything up when they run in non-headless browsers. I personally use the following code in my Test Suite in the "onPrepare" function in my 'conf.js' file:

除了上面提到的重要提示,我还建议禁用Angular / CSS动画,以便在非无头浏览器中运行时加快速度。我个人在我的'Conf.js'文件中的“onPrepare”函数中使用我的Test Suite中的以下代码:

onPrepare: function() {
    var disableNgAnimate = function() {
        angular
            .module('disableNgAnimate', [])
            .run(['$animate', function($animate) {
                $animate.enabled(false);
            }]);
    };

    var disableCssAnimate = function() {
        angular
            .module('disableCssAnimate', [])
            .run(function() {
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = '* {' +
                    '-webkit-transition: none !important;' +
                    '-moz-transition: none !important' +
                    '-o-transition: none !important' +
                    '-ms-transition: none !important' +
                    'transition: none !important' +
                    '}';
                document.getElementsByTagName('head')[0].appendChild(style);
            });
    };

    browser.addMockModule('disableNgAnimate', disableNgAnimate);
    browser.addMockModule('disableCssAnimate', disableCssAnimate);
}

Please note: I did not write the above code, I found it online while looking for ways to speed up my own tests.

请注意:我没有写上面的代码,我在寻找加速自己测试的方法时在网上找到了它。

#6


2  

From what I know:

据我所知:

  • run test in parallel
  • 并行运行测试
  • inject data in case you are only testing a UI element
  • 在您仅测试UI元素的情况下注入数据
  • use CSS selectors, no xpath (browsers have a native engine for CSS, and the xpath engine is not performance as CSS engine)
  • 使用CSS选择器,没有xpath(浏览器有CSS的本机引擎,而xpath引擎不是CSS引擎的性能)
  • run them on high performant machines
  • 在高性能的机器上运行它们
  • use as much as possible beforeAll() and beforeEach() methods for instructions that you repeat often in multiple test
  • 尽可能多地使用beforeAll()和beforeEach()方法来获取在多次测试中经常重复的指令

#7


1  

Using Phantomjs will considerably reduce the duration it takes in GUI based browser, but better solution I found is to manage tests in such a way that it can be run in any order independently of other tests, It can be achieved easily by use of ORM(jugglingdb, sequelize and many more) and TDB frameworks, and to make them more manageable one can use jasmine or cucumber framework, which has before and after hookups for individual tests. So now we can gear up with maximum instances our machine can bear with "shardTestFiles: true".

使用Phantomjs将大大减少基于GUI的浏览器所需的持续时间,但我发现更好的解决方案是以独立于其他测试的任何顺序运行测试,可以通过使用ORM轻松实现( jugglingdb,sequelize和更多)和TDB框架,并使它们更易于管理,可以使用茉莉或黄瓜框架,它具有针对个别测试的连接之前和之后。所以现在我们可以通过“shardTestFiles:true”来支持我们的机器可以承受的最大实例。

#1


10  

We currently use "shardTestFiles: true" which runs our tests in parallel, this could help if you have multiple tests.

我们目前使用“shardTestFiles:true”并行运行我们的测试,如果您有多个测试,这可能会有所帮助。

I'm not sure what you are testing here, whether its the data creation or the end result. If the latter, you may want to consider mocking the data creation instead or bypassing the UI some other way.

我不确定你在这里测试什么,无论是数据创建还是最终结果。如果是后者,您可能需要考虑模拟数据创建,或者以其他方式绕过UI。

#2


7  

Injecting in Data

One thing that you can do that will give you a major boost in performance is to not double test. What I mean by this is that you end up filling in dummy data a number of times to get to a step. Its also one of the major reasons that people need tests to run in a certain order (to speed up data entry).

你可以做的一件事就是给你带来性能上的一个重大提升,就是不要加倍测试。我的意思是你最终会多次填充虚拟数据以达到一个步骤。它也是人们需要测试以某种顺序运行(加速数据输入)的主要原因之一。

An example of this is if you want to test filtering on a grid (data-table). Filling in data is not part of this action. Its just an annoying thing that you have to do to get to testing the filtering. By calling a service to add the data you can bypass the UI and seleniums general slowness (Id also recommend this on the server side by injecting values directly into the DB using migrations).

例如,如果要在网格(数据表)上测试过滤。填写数据不是此操作的一部分。它只是一个烦人的事情,你必须做到测试过滤。通过调用服务来添加数据,您可以绕过UI和selenium一般的缓慢(Id也建议在服务器端通过使用迁移将值直接注入数据库)。

A nice way to do this is to add a helper to your pageobject as follows:

一个很好的方法是在页面对象中添加一个帮助程序,如下所示:

module.exports = {
    projects: {
        create: function(data) {
            return browser.executeAsyncScript(function(data, callback) {
                var api = angular.injector(['ProtractorProjectsApp']).get('apiService');
                api.project.save(data, function(newItem) {
                    callback(newItem._id);
                })
            }, data);
        }
    }
};

The code in this isnt the cleanest but you get the general gist of it. Another alternative is to replace the module with a double or mock using [Protractor#addMockModule][1]. You need to add this code before you call Protractor#get(). It will load after your application services overriding if it has the same name as an existing service.

这里的代码不是最干净的,但你得到了它的一般要点。另一种方法是使用[Protractor#addMockModule] [1]用double或mock替换模块。在调用Protractor#get()之前,需要添加此代码。如果它与现有服务具有相同的名称,它将在应用程序服务覆盖后加载。

You can use it as follows :

您可以按如下方式使用它:

var dataUtilMockModule = function () {
     // Create a new module which depends on your data creation utilities
    var utilModule = angular.module('dataUtil', ['platform']);
    // Create a new service in the module that creates a new entity
    utilModule.service('EntityCreation', ['EntityDataService', '$q', function (EntityDataService, $q) {

        /**
         * Returns a promise which is resolved/rejected according to entity creation success
         * @returns {*}
         */
        this.createEntity = function (details,type) {
            // This is your business logic for creating entities
            var entity = EntityDataService.Entity(details).ofType(type);
            var promise = entity.save();
            return promise;
        };
    }]);
};

browser.addMockModule('dataUtil', dataUtilMockModule);

Either of these methods should give you a significant speedup in your testing.

这些方法中的任何一种都可以为您的测试带来显着的加速。

Sharding Tests

Sharding the tests means splitting up the suites and running them in parallel. To do this is quite simple in protractor. Adding the shardTestFiles and maxInstences to your capabilities config should allow you to (in this case) run at most two test in parrallel. Increase the maxInstences to increase the number of tests run. Note : be careful not to set the number too high. Browsers may require multiple threads and there is also an initialisation cost in opening new windows.

对测试进行分片意味着拆分套件并将它们并行运行。在量角器中这样做非常简单。将shardTestFiles和maxInstences添加到您的功能配置应该允许您(在这种情况下)以并行方式运行最多两次测试。增加maxInstences以增加运行的测试次数。注意:注意不要将数字设置得太高。浏览器可能需要多个线程,并且在打开新窗口时也存在初始化成本。

capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 2
},

Setting up PhantomJS (from protractor docs)

Note: We recommend against using PhantomJS for tests with Protractor. There are many reported issues with PhantomJS crashing and behaving differently from real browsers.

注意:我们建议不要使用PhantomJS进行Protractor测试。有许多报道的问题与PhantomJS崩溃并且与真实浏览器的行为不同。

In order to test locally with PhantomJS, you'll need to either have it installed globally, or relative to your project. For global install see the PhantomJS download page (http://phantomjs.org/download.html). For local install run: npm install phantomjs.

要使用PhantomJS进行本地测试,您需要全局安装或相对于项目安装。有关全局安装,请参阅PhantomJS下载页面(http://phantomjs.org/download.html)。对于本地安装运行:npm install phantomjs。

Add phantomjs to the driver capabilities, and include a path to the binary if using local installation:

将phantomjs添加到驱动程序功能中,如果使用本地安装,则包含二进制文件的路径:

capabilities: {
  'browserName': 'phantomjs',

  /* 
   * Can be used to specify the phantomjs binary path.
   * This can generally be ommitted if you installed phantomjs globally.
   */
  'phantomjs.binary.path': require('phantomjs').path,

  /*
   * Command line args to pass to ghostdriver, phantomjs's browser driver.
   * See https://github.com/detro/ghostdriver#faq
   */
  'phantomjs.ghostdriver.cli.args': ['--loglevel=DEBUG']
}

#3


3  

Another speed tip I've found is that for every test I was logging in and logging out after the test is done. Now I check if I'm already logged in with the following in my helper method;

我发现的另一个速度提示是,每次测试我都会登录并在测试完成后退出。现在我检查我是否已经在我的帮助方法中使用以下内容登录;

  # Login to the system and make sure we are logged in.
  login: ->
    browser.get("/login")
    element(By.id("username")).isPresent().then((logged_in) ->
      if logged_in == false
        element(By.id("staff_username")).sendKeys("admin")
        element(By.id("staff_password")).sendKeys("password")
        element(By.id("login")).click()
    )

#4


2  

I'm using grunt-protractor-runner v0.2.4 which uses protractor ">=0.14.0-0 <1.0.0". This version is 2 or 3 times faster than the latest one (grunt-protractor-runner@1.1.4 depending on protractor@^1.0.0)

我正在使用grunt-protractor-runner v0.2.4,它使用量角器“> = 0.14.0-0 <1.0.0”。这个版本比最新版本快2到3倍(grunt-protractor-runner@1.1.4取决于protractor@^1.0.0)

So I suggest you to give a try and test a previous version of protractor

因此,我建议您尝试并测试以前版本的量角器

Hope this helps

希望这可以帮助

#5


2  

Along with the great tips found above I would recommend disabling Angular/CSS Animations to help speed everything up when they run in non-headless browsers. I personally use the following code in my Test Suite in the "onPrepare" function in my 'conf.js' file:

除了上面提到的重要提示,我还建议禁用Angular / CSS动画,以便在非无头浏览器中运行时加快速度。我个人在我的'Conf.js'文件中的“onPrepare”函数中使用我的Test Suite中的以下代码:

onPrepare: function() {
    var disableNgAnimate = function() {
        angular
            .module('disableNgAnimate', [])
            .run(['$animate', function($animate) {
                $animate.enabled(false);
            }]);
    };

    var disableCssAnimate = function() {
        angular
            .module('disableCssAnimate', [])
            .run(function() {
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = '* {' +
                    '-webkit-transition: none !important;' +
                    '-moz-transition: none !important' +
                    '-o-transition: none !important' +
                    '-ms-transition: none !important' +
                    'transition: none !important' +
                    '}';
                document.getElementsByTagName('head')[0].appendChild(style);
            });
    };

    browser.addMockModule('disableNgAnimate', disableNgAnimate);
    browser.addMockModule('disableCssAnimate', disableCssAnimate);
}

Please note: I did not write the above code, I found it online while looking for ways to speed up my own tests.

请注意:我没有写上面的代码,我在寻找加速自己测试的方法时在网上找到了它。

#6


2  

From what I know:

据我所知:

  • run test in parallel
  • 并行运行测试
  • inject data in case you are only testing a UI element
  • 在您仅测试UI元素的情况下注入数据
  • use CSS selectors, no xpath (browsers have a native engine for CSS, and the xpath engine is not performance as CSS engine)
  • 使用CSS选择器,没有xpath(浏览器有CSS的本机引擎,而xpath引擎不是CSS引擎的性能)
  • run them on high performant machines
  • 在高性能的机器上运行它们
  • use as much as possible beforeAll() and beforeEach() methods for instructions that you repeat often in multiple test
  • 尽可能多地使用beforeAll()和beforeEach()方法来获取在多次测试中经常重复的指令

#7


1  

Using Phantomjs will considerably reduce the duration it takes in GUI based browser, but better solution I found is to manage tests in such a way that it can be run in any order independently of other tests, It can be achieved easily by use of ORM(jugglingdb, sequelize and many more) and TDB frameworks, and to make them more manageable one can use jasmine or cucumber framework, which has before and after hookups for individual tests. So now we can gear up with maximum instances our machine can bear with "shardTestFiles: true".

使用Phantomjs将大大减少基于GUI的浏览器所需的持续时间,但我发现更好的解决方案是以独立于其他测试的任何顺序运行测试,可以通过使用ORM轻松实现( jugglingdb,sequelize和更多)和TDB框架,并使它们更易于管理,可以使用茉莉或黄瓜框架,它具有针对个别测试的连接之前和之后。所以现在我们可以通过“shardTestFiles:true”来支持我们的机器可以承受的最大实例。