Nightwatch,如何在全球范围内调用“设置”和“拆解”API

时间:2018-02-23 17:24:54

标签: api installation nightwatch.js teardown

我刚刚开始学习nightwatchjs来测试我的webapp。我需要分别在其他所有内容之前和之后调用“setup”和“teardown”脚本。这些脚本在数据库中创建必要的条件,以便运行测试(创建测试许可证,用户等),然后将其删除。我的应用中有一个API调用触发了这些调用。

在globals.js中,您可以设置应在其他所有内容之前和之后执行的beforeafter方法,以及之前应执行的beforeEachafterEach在每个测试套件之后,如果我没有弄错的话。似乎beforeEachafterEach方法接受browser对象和done回调作为参数。但是,beforeafter方法仅获得done回调。

在特定的测试套件中,可以添加相同的四种方法,但在这种情况下,beforeafter分别在所有内容和所有内容之后运行,beforeEach并且afterEach在套件中的每个单独测试之前和之后运行。

理想情况下,我会在全局setupteardown方法中调用我的beforeafter脚本,但这些脚本不会获得夜间守望(浏览器)的实例,所以我不知道我该怎么做。

我可以在我的全局beforeEach方法中启动'setup'调用。这对我来说并不理想,但它仍然可以工作,它只是一个多余的(在每个测试套件之前调用它,而不是在所有测试套件之前调用它)。

但是,当我尝试从全局teardown方法调用afterEach脚本时,我遇到了问题。当我运行测试时,输出会在结束时挂起,直到我点击CTRL+C

这是我的nightwatch.conf.js:

const seleniumServer = require("selenium-server");
const chromedriver = require("chromedriver");


// we use a nightwatch.conf.js file so we can include comments and helper functions
module.exports = {
    "src_folders": [
        "tests",
    ],
    "page_objects_path": './pages',
    "globals_path": "./globals.js",
    "output_folder": "./reports", // reports (test outcome) output by nightwatch
    "custom_commands_path" : "./commands",
    "selenium": {
        "start_process": true, // tells nightwatch to start/stop the selenium process
        "server_path": seleniumServer.path,
        "host": "127.0.0.1",
        "port": 4444, // standard selenium port
        "cli_args": {
            "webdriver.chrome.driver" : chromedriver.path
        }
    },
    "test_settings": {
        "default": {
            "silent": true,
            "launchUrl": 'http://local.mytestwebsite.com',
            "screenshots": {
                "enabled": true, // if you want to keep screenshots
                "path": "./screenshots/" // save screenshots here
            },
            "globals": {
                "waitForConditionTimeout": 5000 // sometimes internet is slow so wait.
            },
            "desiredCapabilities": { // use Chrome as the default browser for tests
                "browserName": "chrome",
                "chromeOptions": {
                    "args": [
                        "window-size=1366,768",
                        "--incognito"
                    ]
                }
            }
        }
    }
}

这是我的globals.js:

var chromedriver = require('chromedriver');
module.exports = {


    beforeEach: function(browser, done) {
        console.log('Executing the global `beforeEach`');

        browser.url('http://www.vulfpeck.com');
        browser.expect.element('body').to.be.present;
        browser.end();

        // getting the session info
        browser.status(function(result) {
            console.log("Session Info: ", result.value);
            done();
        });
    },


    afterEach: function(browser, done){
        console.log('Executing the global `afterEach`');

        browser.url('http://www.vulfpeck.com');
        browser.expect.element('body').to.be.present;
        browser.end();

        // getting the session info
        browser.status(function(result) {
            console.log("Session Info: ", result.value);
            done();
        });
    },


    before: function(done) {
        console.log('Executing the global `before`');
        console.log('starting the chromedriver');
        chromedriver.start();
        done();
    },


    after: function(done) {
        console.log('Executing the global `after`');
        console.log('stoppin the chromedriver');
        chromedriver.stop();
        done();
    }
};

这是我的测试套件:

module.exports = {
    'Test 1': function(browser){
        browser.url('http://www.google.com');
        browser.expect.element('body').to.be.present;
        browser.end();
    },
    'Test 2': function(browser){
        browser.url('http://www.vulfpeck.com');
        browser.expect.element('body').to.be.present;
        browser.end();
    },
    before: function(browser, done){
        console.log('test before');
        done();
    },
    beforeEach: function(browser, done){
        console.log('test beforeEach');
        done();
    },
    after: function(browser, done){
        console.log('test after');
        done();
    },
    afterEach: function(browser, done){
        console.log('test afterEach');
        done();
    }
};

这是输出。

$ nightwatch
Executing the global `before`
starting the chromedriver
Starting selenium server... started - PID:  11772

[Login] Test Suite
======================
Executing the global `beforeEach`
 √ Expected element <body> to be present - element was present in 31ms
Session Info:  { ready: true,
  message: 'Server is running',
  build:
   { revision: '63f7b50',
     time: '2018-02-07T22:42:28.403Z',
     version: '3.9.1' },
  os: { arch: 'amd64', name: 'Windows 10', version: '10.0' },
  java: { version: '9' } }
test before

Running:  Test 1
test beforeEach
 √ Expected element <body> to be present - element was present in 30ms
test afterEach

OK. 1 assertions passed. (3.56s)

Running:  Test 2
test beforeEach
 √ Expected element <body> to be present - element was present in 20ms
test afterEach

OK. 1 assertions passed. (2.503s)
test after
Executing the global `afterEach`
Session Info:  { ready: true,
  message: 'Server is running',
  build:
   { revision: '63f7b50',
     time: '2018-02-07T22:42:28.403Z',
     version: '3.9.1' },
  os: { arch: 'amd64', name: 'Windows 10', version: '10.0' },
  java: { version: '9' } }
 × Expected element <body> to be present - element was not found  - expected "present" but got: "not present"
    at Object.afterEach (C:\sites\mytestwebsite.com\selenium\globals.js:29:21)

那么,我错过了什么吗?为什么我不能在没有挂起的全局afterEach方法中点击URL? (我只是想通过,如果我从套件中的上一次测试中删除browser.end();,我的全局afterEach将正常工作。为什么会这样?)。在运行所有测试之前和之后是否有其他推荐的方法来访问URL?

谢谢!任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

虽然我还没有完全回答我自己的问题,但我想出了另一种方法来在全局beforeafter挂钩中调用我的设置和拆卸脚本。

为此,我安装了节点libarary child_process(通过键入npm install child_process),这允许我在命令行上执行命令。

在我的globals.js中,我要求顶部的图书馆:

const { exec } = require('child_process');

在我的beforeafter个钩子中,我正在使用它:

exec('php ../run.php api selenium setup', (err, stdout, stderr) => {
            if (err) {
                // node couldn't execute the command
                console.log("node couldn't execute the command",err);
                done();
                return;
            }

            // the *entire* stdout and stderr (buffered)
            console.log(`stdout: ${stdout}`);
            console.log(`stderr: ${stderr}`);
            done();
        });

希望这有助于某人。