【问题标题】:How to make a globally accessible variable?如何制作全局可访问的变量?
【发布时间】:2014-09-23 21:35:02
【问题描述】:

如何在 nightwatch.js 中创建一个全局可访问的变量?我正在使用一个变量来存储一个自定义的 url(取决于我们的在线产品中加载了哪个商店),但我需要它可以跨多个 javascript 函数访问。它的值似乎在每个函数结束后都会重置,尽管它是在文件头部的函数之外声明的。

【问题讨论】:

  • 听起来你需要在 Javascript 中阅读 variable scope
  • 对我来说,对全局变量的需求预示着糟糕的软件设计。我的经验是,通常可以通过适当的封装来消除全局变量。例如,您说您需要在多个函数中使用相同的变量。有什么东西阻止您将这些函数放在一个对象中,并在该对象上使用属性(状态)而不是全局变量?常量是例外,它们通常作为全局变量非常好。看看你的框架是否不能帮助你进行封装,例如 AngularJS 有一个依赖注入系统(我不知道 nightwatch)。
  • @harbichidian 我并不需要一些令人耳目一新的东西,但是您熟悉使用 nightwatch 进行端到端测试吗?它表现出一些与典型 javascript 功能不匹配的非典型行为,在这种情况下涉及变量范围。
  • @tmacarthur 我很抱歉,那么。我可以建议您提及您尝试过的解决方案吗?这通常有助于获得有用的答案。
  • @EmilLundberg 用于配置全局变量没问题。

标签: javascript nightwatch.js


【解决方案1】:

globals.json 的替代方案如果您需要读取具有复杂过程的数据,只需在同一个测试文件中创建一个函数。

在以下示例中,我需要来自 csv 的简单值和数据。
所以我创建了 getData() 函数,我可以直接从内部调用:

let csvToJson = require('convert-csv-to-json');

function getData(){
  let users = csvToJson.getJsonFromCsv("/../users.csv");
  return {
    "users:": users,
    "wordToSearch":"JRichardsz"
  }
}

module.exports = {
    
    "login": function(browser) {

      //data is loading here
      var data = getData();

      browser
           .url('https://www.google.com')
           .waitForElementVisible('input[name="q"]', 4000)
           .setValue('input[name="q"]', data.wordToSearch)
           .keys(browser.Keys.ENTER)
           .waitForElementVisible('#result-stats', 4000)
           .end();
    }
};

【讨论】:

    【解决方案2】:

    您已经有一段时间没有提出问题并支持您所要求的内容可能以前(本机)不可用。现在是。

    在开发人员指南中,提供了两种方法来创建可从任何给定测试访问的全局变量,具体取决于您的需要。请参阅here 以获得良好的阅读体验。

    方法一: 对于真正的全局全局变量,即所有测试和所有环境。在 nightwatch.json 文件的“globals_path”部分定义一个对象或传递一个文件,即

    "globals_path": "./lib/globals.js",
    

    但是,您将需要导出变量,因此重温 Node 是个好主意。这是一个基本的 globals.js 文件示例:

    var userNames = {
      basicAuth: 'chicken',
      clientEmail: 'SaddenedSnail@domain.com',
      adminEmail: 'admin@domain.com',
    };
    
    module.exports = {
      userNames: userNames
    }
    

    此对象/文件将用于所有您的测试,无论环境如何,除非您指定不同的文件/对象,如下面的方法 2 所示。

    要访问测试套件中的变量,请使用传递给每个函数(测试)的强制浏览器/客户端变量,即:

     'Account Log In': function accLogin(client) {
        var user = client.globals.userNames.clientEmail;
    
        client
          .url(yourUrl)
          .waitForElementVisible('yourUserNameField', 1000)
          .setValue('yourUserNameField', user)
          .end();
    }
    

    方法二: 对于基于环境的全局变量,它会根据您指定的环境而变化。在您需要的环境下嵌套的 nightwatch.json 文件的“全局”部分定义一个对象或传递一个文件。即

    "test_settings" : {
        "default" : {
          "launch_url" : "http://localhost",
          "selenium_port"  : 4444,
          "selenium_host"  : "localhost",
          "globals": {
            "myGlobal" : "some_required_global"
          }
        }
    }
    

    请注意,在撰写本文时,nightwatch 中似乎存在错误,因此使用方法 2 传递文件不起作用(至少在我的环境中)。有关该错误的更多信息可以找到here

    【讨论】:

      【解决方案3】:

      我可能会因此而被否决,但我已成功用于存储和检索对象和数据的另一个选项是将文件作为键值对写入现有文件。

      这使我可以在测试运行结束时查看随机创建的任何数据。我在我的第一个测试脚本中使用我将用于为测试创建各种帐户的所有数据创建了这个文件。这样,如果我看到很多失败,我可以查看文件并查看使用了哪些数据,然后说,以该用户身份登录并手动转到该位置。

      在自定义命令中,我有一个导出以下函数的文件:

      saveToFile : function(path, filename, data) {
          this.yfs = fs;
          buffer = new Buffer(data);
      
          console.log("Note: About to update the configuration with test data" )
      
          fs.open(path, 'w', function(err, fd) {
              if (err) {
                  throw 'error opening file: ' + err;
              }
      
              fs.write(fd, buffer, 0, buffer.length, null, function(err) {
                  if (err) throw 'error writing file: ' + err;
                   return fs.close(fd, function() {
                      console.log('File write: ' +  path + ' has been updated.' );
                  })
              });
          })
      },
      

      在此文件中,“数据”是键值对,例如“用户名”:“Randy8989@mailinator.com”。因此,如果需要,我可以在以后的脚本中使用该数据。

      这是真的,我将立即探索 GrayedFox 的答案。

      【讨论】:

        【解决方案4】:

        为了扩展 Tricote 的答案,Nightwatch 对此提供了内置支持。请参阅documentation

        您可以在nightwatch.json 文件中将其指定为"globals": {"myvar": "whatever"},或在nightwatch.json 中使用"globals": "path/to/globals.js" 引用的globals.js 文件中指定。在后一种情况下,globals.js 可能有:

        module.exports = {
          myvar: 'whatever'
        };
        

        在任何一种情况下,您都可以在测试中访问变量,如 Tricote 所述:

        module.exports = {
          "test": function(browser) {
            console.log(browser.globals.myvar); // "whatever"
          }
        };
        

        【讨论】:

          【解决方案5】:

          不确定这是不是最好的方法,但我是这样做的:您可以在 browser.globals 中定义一个变量并在不同的测试中访问它

          例如:

           module.exports = {
            before: function(browser) {
              console.log("Setting up...");
          
              // initialize global variable state
              browser.globals.state = {};
            },
          
            "first test": function(browser) {
              var settings = browser.globals,
                  state = browser.globals.state;
          
              state.my_shared_var = "something";
          
              browser.
                // ...
                // use a shared variable
                .setValue('input#id', state.my_shared_var)
                // ...
          
                // ...
                // save something from the page in a variable 
                .getText("#result", function(result) {
                  state.my_shared_result = result.value;
                })
                // ...
            },
          
            "second test": function(browser) {
              var settings = browser.globals,
                  state = browser.globals.state;
          
              browser.
                // ...
                // use the variables
                .url("http://example.com/" + state.my_shared_result + "/show")
                .assert.containsText('body', state.my_shared_var)
                // ...
            }
          }
          

          【讨论】:

          • beforeEachafterEach 接收浏览器对象。 beforeafter 只接收 done 回调。
          【解决方案6】:

          通常这是一种不好的做法,但您可以将其分配为 window 类的字段。

          window.someGlobalVar = 'http://example.org/'
          

          window 对象可以全局访问

          【讨论】:

          • 在一般情况下,这是正确的。然而,在守夜人中却不是这样。
          猜你喜欢
          • 2016-05-04
          • 1970-01-01
          • 2015-03-30
          • 2012-10-11
          • 1970-01-01
          • 1970-01-01
          • 2016-09-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多