【问题标题】:Using require with relative paths将 require 与相对路径一起使用
【发布时间】:2015-07-18 14:03:16
【问题描述】:

我们在 Protractor 上进行了相当多的端到端测试。我们遵循页面对象模式,这有助于我们保持测试的清洁和模块化。我们还有一组帮助函数可以帮助我们关注DRY principle

问题:

单个规范可能需要多个页面对象和帮助模块。例如:

"use strict";

var helpers = require("./../../helpers/helpers.js");
var localStoragePage = require("./../../helpers/localStorage.js");
var sessionStoragePage = require("./../../helpers/sessionStorage.js");

var loginPage = require("./../../po/login.po.js");
var headerPage = require("./../../po/header.po.js");
var queuePage = require("./../../po/queue.po.js");

describe("Login functionality", function () {

    beforeEach(function () {
        browser.get("/#login");

        localStoragePage.clear();
    });

    // ...

});

您可以看到我们在每个 require 语句中都有该目录遍历:./../..。这是因为我们有一个 specs 目录,我们将规范和多个目录保存在其中,这些目录按正在测试的应用程序功能分组。

问题:

在量角器中解决相对路径问题的规范方法是什么?

换句话说,我们希望避免遍历树,向上导入模块。而是从基本应用程序目录中向下移动会更干净。


尝试和想法:

有一篇关于解决这个问题的好文章:Better local require() paths for Node.js,但我不确定在使用 Protractor 开发测试时推荐哪个选项。

我们也尝试使用require.main 来构造路径,但它指向node_modules/protractor 目录而不是我们的应用程序目录。

【问题讨论】:

    标签: javascript angularjs testing protractor


    【解决方案1】:

    我遇到了同样的问题,最终得到了以下解决方案。 在我的 Protractor 配置文件中,我有一个变量,它存储了我的 e2e 测试的基本文件夹的路径。此外,Protractor 配置提供了onPrepare 回调,您可以在其中使用名为global 的变量为您的测试创建全局变量。您将它们定义为 global 变量的属性,并使用与在测试中使用全局变量 browserelement 相同的方式。我用它来创建自定义全局 require 函数来加载不同类型的实体:

    // __dirname retuns a path of this particular config file
    // assuming that protractor.conf.js is in the root of the project
    var basePath = __dirname + '/test/e2e/';
    // /path/to/project/test/e2e/
    
    exports.config = {
    
        onPrepare: function () {
    
            // "relativePath" - path, relative to "basePath" variable
    
            // If your entity files have suffixes - you can also keep them here
            // not to mention them in test files every time
    
            global.requirePO = function (relativePath) {
                return require(basePath + 'po/' + relativePath + '.po.js');
            };
    
            global.requireHelper = function (relativePath) {
                return require(basePath + 'helpers/' + relativePath + '.js');
            };
    
        }
    
    };
    

    然后您可以立即在测试文件中使用这些全局实用方法:

    "use strict";    
    
    var localStorageHelper = requireHelper('localStorage');
    // /path/to/project/test/e2e/helpers/localStorage.js 
    
    var loginPage = requirePO('login');
    // /path/to/project/test/e2e/po/login.po.js
    
    var productShowPage = requirePO('product/show');
    // /path/to/project/test/e2e/po/product/show.po.js
    
    
    describe("Login functionality", function () {
    
        beforeEach(function () {
            browser.get("/#login");
    
            localStorageHelper.clear();
        });
    
        // ...
    
    });
    

    【讨论】:

      【解决方案2】:

      我们一直面临同样的问题,因此决定将所有页面对象和帮助文件转换为节点包。在测试中要求它们现在就像var Header = require('header-po') 一样简单。转换为包的另一个好处是您可以使用正确的版本控制。

      这是一个简单的例子:

      ./page-objects/header-po/index.js

      //page-objects/header-po/index.js
      
      'use strict';
      
      var Header = function () {
          this.goHome = function () {
              $('#logo a').click();
          };
        };
      
      module.exports = Header;
      

      ./page-objects/header-po/package.json

      {
          "name": "header-po",
          "version": "0.1.1",
          "description": "Header page object",
          "main": "index.js",
          "dependencies": {}
      }
      

      ./package.json

      {
          "name": "e2e-test-framework",
          "version": "0.1.0",
          "description": "Test framework",
          "dependencies": {
              "jasmine": "^2.1.1",
              "header-po": "./page-objects/header-po/",
          }
      }
      

      ./tests/header-test.js

      'use strict';
      
      var Header = require('header-po');
      
      var header = new Header();
      
      describe('Header Test', function () {
          it('clicking logo in header bar should open homepage', function () {
              browser.get(browser.baseUrl + '/testpage');
              header.goHome();
              expect(browser.getCurrentUrl()).toBe(browser.baseUrl);
          });
      });
      

      【讨论】:

        【解决方案3】:

        我也遇到了同样的问题。与 Michael Radionov 的解决方案类似,但没有设置全局函数,而是将属性设置为量角器本身。

        量角器.conf.js

        onPrepare: function() {
          protractor.basePath = __dirname;
        }
        

        test-e2e.js

        require(protractor.basePath+'/helpers.js');
        
        describe('test', function() {
           .......
        });
        

        【讨论】:

          【解决方案4】:

          我认为我们在我工作的地方使用的方法可能对您来说是一个很好的解决方案。我已经发布了一个关于我们如何处理所有事情的简短示例。非常棒的 b/c,您可以在任何规范文件中调用页面对象函数,而无需在规范中使用 require。

          Call a node module from another module without using require() everywhere

          【讨论】:

            【解决方案5】:

            所有答案似乎都是解决方法

            实际可行的解决方案是这样的:

                "_moduleAliases": {
                    "@protractor": "protractor/_protractor",
                    "@tmp": "protractor/.tmp_files",
                    "@test_data": "protractor/.tmp_files/test_data",
                    "@custom_implementation": "protractor/custom_implementation",
                },
            
            • 将此添加为量角器配置的第一行
            require('module-alias/register');
            
            • 像这样在项目的任何地方使用它
            const params = require('@test_data/parameters');
            const customImplementation require('@custom_implementation')
            // etc
            

            【讨论】:

            • 我希望我没有错过任何重要的事情,因为我在 2 年前实现了这个并且仍然在没有修改的情况下使用它。告诉我
            猜你喜欢
            • 2011-07-19
            • 2020-10-16
            • 2019-10-29
            • 1970-01-01
            • 2011-06-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多