Javascript 如何正确地将casperjs测试与共享浏览器实例分开

Javascript 如何正确地将casperjs测试与共享浏览器实例分开,javascript,node.js,casperjs,Javascript,Node.js,Casperjs,我正在尝试测试“大部分”单页应用程序的不同部分。我想把测试分开,但我真的只想加载一次页面,然后让测试通过,然后点击链接等等 这是我的密码: PRE.js var port = require('system').env.PORT var tester; casper.options.viewportSize = {width: 1024, height: 768}; casper.test.begin('Test login', function suite(test) { var

我正在尝试测试“大部分”单页应用程序的不同部分。我想把测试分开,但我真的只想加载一次页面,然后让测试通过,然后点击链接等等

这是我的密码:

PRE.js

var port = require('system').env.PORT
var tester;

casper.options.viewportSize = {width: 1024, height: 768};

casper.test.begin('Test login', function suite(test) {
    var done = false;
    casper.on("page.error", function(msg, trace) {
        this.echo("Error:    " + msg, "ERROR");
        this.echo("file:     " + trace[0].file, "WARNING");
        this.echo("line:     " + trace[0].line, "WARNING");
        this.echo("function: " + trace[0]["function"], "WARNING");
    });

    casper.on('remote.message', function(message) {
        this.echo('remote message caught: ' + message);
        if (message == "done") { 
            done = true;
        }
    });

    casper.start('http://localhost:' + port, function() {

    // Verify that the main menu links are present.
        test.assertExists('input[name=username]');
        // 10 articles should be listed.
        test.assertElementCount('input', 3);
        casper.fill("form", {
            "username": "username",
            "password": "my password goes right here you cant have it"
        }, true);
        casper.then(function() {
                casper.waitFor(function(){
                    return done;
                    }, function(){
                    tester = casper.evaluate(function(){
                        return tester;
                    });
                    test.assert("undefined" != typeof tester);
                    test.assert(Object.keys(tester).length > 0);
                });
        });
    });

    casper.run(function() {
        test.done();
    });
});
然后我有第二个文件(还有更多类似的文件): TEST.js

我希望从pre.js获得浏览器会话的屏幕截图

我从启动我的程序的专门程序运行它,但本质上它运行:

casperjs test casper_tests --pre=pre.js
casper_测试保存上述两个文件

我的问题:


正确的方法是什么?没有截图,也许更重要的是(尽管我还没有尝试过),我希望能够点击里面的东西,并验证其他部分是否正常工作。屏幕截图只是验证我是否在正确的社区。

这不太可能,而且有潜在的危险。您所做的每一个操作都需要反向执行,以不破坏其他测试。如果您后来决定以模块化的方式编写测试是件好事,那么编写测试会让您头疼

PRE.js将是您的开始脚本,您可以修改它来执行中间的测试。在下面的完整工作示例中,您将看到如何为casper的一次执行安排多个测试用例。这是不好的,因为
画布
测试用例取决于
链接
测试用例的正确执行

casper.start('http://example.com');
casper.then(function() {
    this.test.begin("link", function(test){
        var url = casper.getCurrentUrl();
        test.assertExists("a");
        casper.click("a");
        casper.then(function(){
            test.assert(this.getCurrentUrl() !== url);
            this.back(); // this is bad
            test.done();
        });
    });
    this.test.begin("canvas", function(test){
        test.assertNotExists("canvas");
        test.done();
    });
});
casper.run();
当然,您可以为新的测试用例再次打开根目录,但随后您会遇到与初始代码相同的问题

var url = 'http://example.com';
casper.start();
casper.thenOpen(url, function() {
    this.test.begin("link", function(test){
        var url = casper.getCurrentUrl();
        test.assertExists("a");
        casper.click("a");
        casper.then(function(){
            test.assert(this.getCurrentUrl() !== url);
            test.done();
        });
    });
});
casper.thenOpen(url, function() {
    this.test.begin("canvas", function(test){
        test.assertNotExists("canvas");
        test.done();
    });
});
casper.run();
现在,测试用例不再相互依赖,但是您也可以多次加载页面


如果您需要为每个测试用例执行一些初始操作,那么PRE.js不是合适的地方

创建include.js并将以下代码放在那里:

function login(suite, username, password){
    username = username || "defaultUsername";
    password = password || "defaultPassword";
    casper.test.begin('Test login', function suite(test) {
        var done = false;
        // event handlers

        casper.start('http://localhost:' + port, function() {
            // login if the session expired or it is the first run
            if (!loggedIn) {
                // login
            }
            // wait
        });

        casper.then(function(){
            suite.call(casper, test);
        });

        casper.run(function() {
            test.done();
        });
    });
}
然后,您可以将其作为
casperjs test casper\u tests运行--includes=include.js
,测试文件如下

login(function(test){
    this.click("#something");
    this.waitForSelector(".somethingChanged");
    this.then(function(){
        test.assertExists(".somethingElseAlsoHappened");
    });
});
当然,您可以使用不同的
登录
功能(使用不同的名称)或更轻量级的功能


在前面的代码段的基础上,您可以创建一个开始脚本并自己加载测试文件。然后你就有了做这件事所需要的所有灵活性

include.js:

function login(testScript, username, password, next){
    // event handlers

    casper.start('http://localhost:' + port, function() {
        // login if the session expired or it is the first run
        // waiting
    });

    testScript.forEach(function(case){
        casper.thenOpen(case.name, function(){
            this.test.begin(function suite(test){
                case.func.call(casper, test);
                casper.then(function(){
                    test.done();
                });
            });
        });
    });

    casper.run(next);
}
start.js:

// pass the test file folder to the script and read it with sys.args
// fs.list(path) all files in that path and iterate over them
var filesContents = files.map(function(filename){
    return require(filename).testcases;
});
var end = null;
// stack the test cases into the `run` callback of the previous execution
filesContents.forEach(function(case){
    var newEnd = end;
    var newFunc = function(){ login(case, u, p, newEnd) };
    end = newFunc;
});
end(); // run the stack in reverse
每个测试文件如下所示:

exports.testcases = [
    {
        name: "sometest",
        func: function(test){
            test.assert(true)
            this.echo(this.getCurrenturl());
        }
    },
    {
        name: "sometest2",
        func: function(test){
            test.assert(true)
            this.echo(this.getCurrenturl());
        }
    },
];

这只是一个建议。

这不太可能,而且有潜在的危险。您所做的每一个操作都需要反向执行,以不破坏其他测试。如果您后来决定以模块化的方式编写测试是件好事,那么编写测试会让您头疼

PRE.js将是您的开始脚本,您可以修改它来执行中间的测试。在下面的完整工作示例中,您将看到如何为casper的一次执行安排多个测试用例。这是不好的,因为
画布
测试用例取决于
链接
测试用例的正确执行

casper.start('http://example.com');
casper.then(function() {
    this.test.begin("link", function(test){
        var url = casper.getCurrentUrl();
        test.assertExists("a");
        casper.click("a");
        casper.then(function(){
            test.assert(this.getCurrentUrl() !== url);
            this.back(); // this is bad
            test.done();
        });
    });
    this.test.begin("canvas", function(test){
        test.assertNotExists("canvas");
        test.done();
    });
});
casper.run();
当然,您可以为新的测试用例再次打开根目录,但随后您会遇到与初始代码相同的问题

var url = 'http://example.com';
casper.start();
casper.thenOpen(url, function() {
    this.test.begin("link", function(test){
        var url = casper.getCurrentUrl();
        test.assertExists("a");
        casper.click("a");
        casper.then(function(){
            test.assert(this.getCurrentUrl() !== url);
            test.done();
        });
    });
});
casper.thenOpen(url, function() {
    this.test.begin("canvas", function(test){
        test.assertNotExists("canvas");
        test.done();
    });
});
casper.run();
现在,测试用例不再相互依赖,但是您也可以多次加载页面


如果您需要为每个测试用例执行一些初始操作,那么PRE.js不是合适的地方

创建include.js并将以下代码放在那里:

function login(suite, username, password){
    username = username || "defaultUsername";
    password = password || "defaultPassword";
    casper.test.begin('Test login', function suite(test) {
        var done = false;
        // event handlers

        casper.start('http://localhost:' + port, function() {
            // login if the session expired or it is the first run
            if (!loggedIn) {
                // login
            }
            // wait
        });

        casper.then(function(){
            suite.call(casper, test);
        });

        casper.run(function() {
            test.done();
        });
    });
}
然后,您可以将其作为
casperjs test casper\u tests运行--includes=include.js
,测试文件如下

login(function(test){
    this.click("#something");
    this.waitForSelector(".somethingChanged");
    this.then(function(){
        test.assertExists(".somethingElseAlsoHappened");
    });
});
当然,您可以使用不同的
登录
功能(使用不同的名称)或更轻量级的功能


在前面的代码段的基础上,您可以创建一个开始脚本并自己加载测试文件。然后你就有了做这件事所需要的所有灵活性

include.js:

function login(testScript, username, password, next){
    // event handlers

    casper.start('http://localhost:' + port, function() {
        // login if the session expired or it is the first run
        // waiting
    });

    testScript.forEach(function(case){
        casper.thenOpen(case.name, function(){
            this.test.begin(function suite(test){
                case.func.call(casper, test);
                casper.then(function(){
                    test.done();
                });
            });
        });
    });

    casper.run(next);
}
start.js:

// pass the test file folder to the script and read it with sys.args
// fs.list(path) all files in that path and iterate over them
var filesContents = files.map(function(filename){
    return require(filename).testcases;
});
var end = null;
// stack the test cases into the `run` callback of the previous execution
filesContents.forEach(function(case){
    var newEnd = end;
    var newFunc = function(){ login(case, u, p, newEnd) };
    end = newFunc;
});
end(); // run the stack in reverse
每个测试文件如下所示:

exports.testcases = [
    {
        name: "sometest",
        func: function(test){
            test.assert(true)
            this.echo(this.getCurrenturl());
        }
    },
    {
        name: "sometest2",
        func: function(test){
            test.assert(true)
            this.echo(this.getCurrenturl());
        }
    },
];

这只是一个建议。

如果我们假设测试用例不必反转,该怎么办?(我完全理解这与正常的测试理念背道而驰)。虽然我会使用include的想法,但它仍然不共享浏览器会话。是的,它共享。如果不删除Cookie,它将是同一个会话。每个测试用例和测试文件都在同一个phantomjs实例上运行,Cookie永远不会从casper本身中删除。对不起,我的意思是在同一个浏览器页面实例中。它仍然需要在每次测试之间重新加载页面,我正试图找到一种避免这种情况的方法(有不同的套件,我希望每个套件在单个浏览器加载中运行)(顺便说一句,我不认为上面的答案是正确的,我肯定会接受建议,我只想知道如何做的另一半)如果我们假设测试用例不必反转,该怎么办?(我完全理解这与正常的测试哲学背道而驰)。虽然我会使用include idea,但它仍然不会共享浏览器会话。是的,它会共享。如果不删除Cookie,它将是同一个会话。每个测试用例和测试文件都在同一个phantomjs实例上运行,Cookie永远不会从casper本身删除。对不起,我的意思是在同一个浏览器页面实例中。它仍然会有要在每次测试之间重新加载页面,我正试图找到一种避免的方法(有不同的套件,我希望每个套件在一个浏览器加载中运行)(顺便说一句,我不认为上面的答案是正确的,我一定会接受建议,我只想找出另外一半的方法)