eckhards
eckhards

Reputation: 171

How to modularize CasperJS test steps?

I am pretty new to CasperJS and I have started creating a test suite. Some of the steps (like logging in to the application) will be reused a lot, so we would like to manage them in library files (which are included in the test files).

Plus, we have multiple environments running (dev, integration, production etc.) so we need to parametrize the test steps for this, so it shall be possible to pass parameters to the modules.

I searched the documentation and stackoverflow (I am aware there are similar questions), but my Javascript skills are too limited obviously and I was not able to get this up and running.

This is my example test file:

// googletesting.js
casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) {
    casper.start("http://www.google.fr/", function() {
        test.assertTitle("Google", "google homepage title is the one expected");
        test.assertExists('form[action="/search"]', "main form is found");
        this.fill('form[action="/search"]', {
            q: "casperjs"
        }, true);
    });

    casper.then(function() {
        test.assertTitle("casperjs - Recherche Google", "google title is ok");
        test.assertUrlMatch(/q=casperjs/, "search term has been submitted");
        test.assertEval(function() {
            return __utils__.findAll("h3.r").length >= 10;
        }, "google search for \"casperjs\" retrieves 10 or more results");
    });

    casper.run(function() {
        test.done();
    });
}); 

And this is how it should be like (or similar):

// googletesting2.js
casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) {

    doGoogleSearch('casperjs'); // pass a search term
    doChecks();

    casper.run(function() {
        test.done();
    });
}); 

Upvotes: 17

Views: 6187

Answers (2)

Fanch
Fanch

Reputation: 3274

Factorize CasperJS

Command :

  $ casperjs test ./scenarios/  

Files :

//login.js, you could also create a js function, var login = function(){...} but i prefer extending, that way i don't mixt js functions and casperjs functions.
casper.login = function (id,password) {
    casper.then(function(){
    this.test.comment('----------------Connexion Only ! : --------------------');
        ...
    });
};

//global.js
var x = require('casper').selectXPath;

casper.on('capture.saved', function(targetFile) {
    this.echo('screen properly done at ' + targetFile);
});
casper.test.on('fail', function() {
    casper.capture('screenshots/fail.png');
});

//test_call_function_login.js
phantom.injectJs( './global.js');   //executed in ccm folder
phantom.injectJs( './_functions/login.js'); 

//or absolute path if you want to execute the test files individually too
phantom.injectJs( 'C:/bin/casperjs/ccm/global.js');
phantom.injectJs( 'C:/bin/casperjs/ccm/_functions/login.js');

//best way to use include for me : you can both execute a folder or a file
phantom.injectJs(fs.workingDirectory + '/../../global.js');

casper.test.begin('\n********* Title suite : ***********\n', 5 , function suite(test) {
    casper.start('http://www.yourUrl.com',function(){
        this.test.assertExists('.search','Search toolbar present');
    })
    .viewport(1200,800)

    .then(function() {
        casper.login("your pseudo","your password");
    })  
    .then(function() {
        this.echo("your tests");
    })  
    .run(function() {
            this.test.comment('----------------------- Steps done ------------------------\n');
            test.done();
    });
});

Global.js : global variables or/and event handlers which can be used everywhere.

You could include your functions too (command), with :

$ casperjs test {...} --includes=/path/to/function1.js,/path/to/function2.js

Here the example : https://gist.github.com/n1k0/3813361

It depends of you if you prefer phantom.injectJS(...) or use command options : --pre (called before all scripts), --includes (called at the beginning of each script-before each one in fact-) .

The folders are executed by alphabetical order, same for the files in folders. You can use 0_file1.js ,1_file2.js to order them, but all my test scripts (or folders scripts) can be executed individually, so it doesn't matter for me.

A bit late i know.

You can also use require() nodeLike : Custom casperjs modules .

Upvotes: 21

sudipto
sudipto

Reputation: 2482

Just put the same code in functions. There are various ways you can pass test to the functions. The simplest way is to pass it as parameter.

casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) {

    doGoogleSearch(test, 'casperjs'); // pass a search term
    doChecks(test);        

    casper.run(function() {
        test.done();
    });
}); 

function doGoogleSearch (test, q) {
    test.assertTitle("Google", "google homepage title is the one expected");
    test.assertExists('form[action="/search"]', "main form is found");
    this.fill('form[action="/search"]', {
        q: q
    }, true);

}

function doChecks (test) {
    test.assertTitle("casperjs - Recherche Google", "google title is ok");
    test.assertUrlMatch(/q=casperjs/, "search term has been submitted");
    test.assertEval(function() {
        return __utils__.findAll("h3.r").length >= 10;
    }, "google search for \"casperjs\" retrieves 10 or more results");
}

Again, if you put these 2 functions inside the scope of suite function, these functions will automatically get access to test.

Other other way is to set it as window.test = test; inside suite and test will be available globally. All functions can access it.

Upvotes: 2

Related Questions