如何使用共享浏览器实例正确分割casperjs测试

时间:2014-08-08 02:53:42

标签: 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 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

casper.test.assert(true);

casper.capture('.screenshot.png');
casper.test.done();

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

我从一个启动我的程序的专门程序运行它,但实际上它运行:

casperjs test casper_tests --pre=pre.js

casper_tests保存上面的两个文件

我的问题:

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

1 个答案:

答案 0 :(得分:4)

这不容易发生,而且有潜在危险。你所做的每一个动作都需要反转,以免打破其他测试。如果您以后决定以模块化方式编写测试是一件好事,那么您将很难编写测试。

PRE.js将是您的启动脚本,您可以修改它以在其间执行测试。在下面的完整工作示例中,您将了解如何为一次执行casper计划多个测试用例。这很糟糕,因为canvas测试用例取决于back测试用例的link执行情况。

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();

当然,您可以再次打开root用于新的测试用例,但是您遇到的问题与初始代码相同。

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_tests --includes=include.js运行
login(function(test){
    this.click("#something");
    this.waitForSelector(".somethingChanged");
    this.then(function(){
        test.assertExists(".somethingElseAlsoHappened");
    });
});

当然,您可以使用不同的login函数(使用不同的名称)或更轻的函数。


在前面的代码段的基础上,您可以创建一个启动脚本并自行加载测试文件。然后,您拥有完成此操作所需的所有灵活性。

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());
        }
    },
];

这只是一个建议。