Python, Selenium and PhantomJS – ignore certificate errors

Background

You are done with your work and push all into Git. The Build-Server starts his work and all test scripts are failing. Short look and it is clear – certificate errors. The next example shows, how to ignore certificate errors on PhantomJS.

@classmethod
def setUpClass(cls):
    """starting point for test cases"""

    cls.driver = webdriver.PhantomJS(service_args=['--ignore-ssl-errors=true'])
    cls.driver.implicitly_wait(30)
    cls.driver.set_window_size(1024, 768)
    cls.driver.get(cls.url)

Now it should work….

Startup with Jasmine

Jasmine is a free JavaScript testing framework for BDD (Behavior Driven Development). In my opinion Unit-test should be written by developers, but tester you need also to know! This tutorial give you a hint how to use it.

Preparation

Download latest standalone version directly from GitHub and unzip. Now you have some files and folders. The file “SpecRunner.html” and “spec”, “src” folders are important for us. Some examples are allready  included. If you run the “SpecRunner.html” in your browser, you can see the first example results. A look inside this examples help you understand Jasmine!

Short Introduction

In the “src” directory, are the things to be tested. The “spec” directory has the tests. The “SpecRunner.html” link to the all files. The comments describe what you should do. Whenever you want to run the tests, you simply need to load or reload.

Example

Delete all files into “src” and “spec” folders. Create on “src” folder a new file.

function say_hello(name) {
    return "hello from " + name;
}
function simple_calc(value_a, value_b) {
    return value_a + value_b;
}
function return_bool(value_a) {
    return isNaN(value_a);
}
var timo = {human: "male"};
var john = {human: "male"};

And on “spec” folder this file.

describe("my first test suite", function() {
    it("test for correct string", function() {
        expect(say_hello("Lisa")).toContain("hello from Lisa");
    });
    it("test for correct value", function() {
        expect(simple_calc(5, 6)).toEqual(11);
    });
    it("test for not a number", function() {
        expect(return_bool("Hello")).toBeTruthy();
    });
    it("test for same object", function() {
        expect(timo).toBe(john);
    });
});

Now edit the “SpecRunner.html”. Just add the paths for JS files.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Jasmine Spec Runner v2.3.4</title>
  <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.3.4/jasmine_favicon.png">
  <link rel="stylesheet" href="lib/jasmine-2.3.4/jasmine.css">
  <script src="lib/jasmine-2.3.4/jasmine.js"></script>
  <script src="lib/jasmine-2.3.4/jasmine-html.js"></script>
  <script src="lib/jasmine-2.3.4/boot.js"></script>
  <!-- include source files here... -->
  <script src="src/example.js"></script>
  <!-- include spec files here... -->
  <script src="spec/example.spec.js"></script>
</head>
<body></body>
</html>

That is it! 😉 Now your results shows 4 Specs with 1 failure.

Network diagnostic with mtr

MTR is a network diagnostic tool which combine the best from Ping and Traceroute. It helps software tester to diagnose network performance and create helpful reports. By mtr, you could also monitor the network. It sends ICMP ECHO requests to a destination and listens for the answers. Mtr works on both command-line and GUI (depending to installation method).

Installation

# Debian/Ubuntu (text-version only)
$ apt-get install mtr-tiny

# Debian/Ubuntu (gui and text-version)
$ apt-get install mtr

# RedHat/CentOS/Fedora (text-version only)
$ yum install mtr-tiny

# RedHat/CentOS/Fedora (gui and text-version)
$ yum install mtr

# Mac OS X (Homebrew)
$ brew install mtr

# Mac OS X (MacPorts)
$ port install mtr

The mtr project is on GitHub. If you like to compile mtr by your self.

Command-line examples

# basic syntax
$ mtr [options] [target]

# example host
$ mtr google.com

# example IP
$ mtr 173.194.40.70

# force text-mode (-t | --curses)
$ mtr -t google.com

# do not resolve host names (-n | --no-dns)
$ mtr -n google.com

# limit to 5 (-c | --report-cycles)
$ mtr -c 5 173.194.40.70

# report mode (-r | --report)
$ mtr -r -c 5 173.194.40.70

# do not cut long names (-w | --report-wide)
$ mtr -r -w -c 5 173.194.40.70

Note: Read the man page for more options!

Report analysis

  • Loss% – Shows packets loss at each hop
  • Snt – Number of packets being sent
  • Last – Latency of the last packet
  • Avg – Average latency of all packets
  • Best – Best round trip time
  • Wrst – Worst round trip time
  • StDev – Standard deviation of the latencies to each host

HAR with Python WebDriver and BrowserMob Proxy

This time is shown how to automate performance test for web sites. Tools in usage are Python Selenium WebDriver and BrowserMob proxy. The results are HAR files which can be viewed in HAR Viewer.

Precondition

  • JAVA installed
  • Python Packages for selenium and browsermob-proxy
selenium
browsermob-proxy

Preparation

Download BrowserMob Proxy and check if proxy can started by command-line.

# change to 
$ cd browsermob-proxy-2.1.0-beta-1/bin/

# start proxy on port 9090
$ ./browsermob-proxy -port 9090

Create Python Class

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Python - BrowserMob - WebDriver"""
from browsermobproxy import Server
from selenium import webdriver
import json


class CreateHar(object):
    """create HTTP archive file"""

    def __init__(self, mob_path):
        """initial setup"""
        self.browser_mob = mob_path
        self.server = self.driver = self.proxy = None

    @staticmethod
    def __store_into_file(title, result):
        """store result"""
        har_file = open(title + '.har', 'w')
        har_file.write(str(result))
        har_file.close()

    def __start_server(self):
        """prepare and start server"""
        self.server = Server(self.browser_mob)
        self.server.start()
        self.proxy = self.server.create_proxy()

    def __start_driver(self):
        """prepare and start driver"""
        profile = webdriver.FirefoxProfile()
        profile.set_proxy(self.proxy.selenium_proxy())
        self.driver = webdriver.Firefox(firefox_profile=profile)

    def start_all(self):
        """start server and driver"""
        self.__start_server()
        self.__start_driver()

    def create_har(self, title, url):
        """start request and parse response"""
        self.proxy.new_har(title)
        self.driver.get(url)
        result = json.dumps(self.proxy.har, ensure_ascii=False)
        self.__store_into_file(title, result)

    def stop_all(self):
        """stop server and driver"""
        self.server.stop()
        self.driver.quit()


if __name__ == '__main__':
    path = "browsermob-proxy-2.1.0-beta-1/bin/browsermob-proxy"
    RUN = CreateHar(path)
    RUN.start_all()
    RUN.create_har('google', 'http://google.com')
    RUN.create_har('stackoverflow', 'http://stackoverflow.com')
    RUN.stop_all()

Note: The highlighted line must contain the path to BrowserMob Proxy!
Happy testing! If you use PhantomJS instead of Firefox, you can use this on Build server like Jenkins/Hudson and so on, too.

UI testing with DalekJS and PhantomJS on CentOS

With DalekJS you can automate your functional GUI tests very easy. This article describe how to prepare the test environment on CentOS.

Setup

First, the necessary packages are installed.

# install EPEL (Extra Packages for Enterprise Linux)
$ yum install -y epel-release

# check repositories
$ yum repolist

# update all
$ yum -y update

# install packages
$ yum install -y vim nodejs npm bzip2 freetype fontconfig

# check versions of nodejs and npm
$ node --version
$ npm --version

# change to tmp folder
$ cd /tmp/

# download PhantomJS and unzip
$ curl -O https://phantomjs.googlecode.com/files/phantomjs-1.9.2-linux-x86_64.tar.bz2
$ tar xvf phantomjs-1.9.2-linux-x86_64.tar.bz2

# copy binary, delete unneeded files and check version
$ cp phantomjs-1.9.2-linux-x86_64/bin/phantomjs /usr/local/bin/
$ rm -fr phantomjs-1.9.2-linux-x86_64
$ rm -f phantomjs-1.9.2-linux-x86_64.tar.bz2
$ phantomjs --version

# install dalek-cli (global) and check version
$ npm install dalek-cli -g
$ dalek --version

It is also possible to compile PhantomJS itself, but this takes a lot of time.

Prepare test project

Once all is installed without any issues you can start to create the test project.

# change to home folder
$ cd ~/

# create project folder and change into
$ mkdir DalekTest && cd DalekTest

# create package.json interactively
$ npm init

# install dalekjs on project
$ npm install dalekjs --save-dev

Create test case

Now it is time for the first Test Case. I have used the example from Dalek website.

# create test case file
$ touch test_title.js

# insert content
$ vim test_title.js
module.exports = {'Page title is correct': function (test) {
  test
    .open('http://google.com')
    .assert.title().is('Google', 'It has title')
    .done();
  }
};

Run test

By default DalekJS use PhantomJS as browser. For running the test case simple use dalek command and as argument the test case file (*.js).

# run test case
$ dalek test_title.js

Full webpage screenshot

For various reasons screenshots for webpages are needed. If automated test scripts fail, documentations must be created or in some other situations. With PhantomJS it is very easy to create these screenshots very fast by command-line. All what is needed a small JavaScript like this.

JavaScript

var phantom;
var console;
var system = require('system');
var fs = require('fs');
var page = require('webpage').create();

var Info = {
	isDate: function () {
		'use strict';
		var mydate = new Date().toDateString();
		return mydate;
	},
	isTime: function () {
		'use strict';
		var mytime = new Date().getTime();
		return mytime;
	}
};

var Target = {
	isLocation: function () {
		'use strict';
		var args = system.args,
		    mylocation = 'http://google.com';
		if (args.length > 1) {
			mylocation = system.args[1];
			console.log('[LOG] use argument location');
		} else {
			console.log('[LOG] use default location');
		}
		return mylocation;
	},
	isSaveFolder: function () {
		'use strict';
		var folder = 'log';
		if (!fs.exists(folder)) {
			console.log('[LOG] creat directory ' + folder);
			fs.makeDirectory(folder);
		}
		if (!fs.isWritable(folder)) {
			console.error('[LOG] ' + folder + ' is not writable!');
			phantom.exit(1);
		}
		return folder;
	}
};

page.open(Target.isLocation(), function (status) {
	'use strict';
	switch (status) {
	case 'success':
		console.log('[LOG] page open successfully' + Info.isDate());
		var folder = Target.isSaveFolder();
		page.render(folder + fs.separator + Info.isTime() + '.png');
		phantom.exit(0);
		break;
	case 'fail':
		console.error('[LOG] page not open successfully');
		phantom.exit(1);
		break;
	default:
		console.error('[LOG] fail to open with unknown status:' + status);
		phantom.exit(1);
		break;
	}
});

After save the script you can run it like:

# screenshot of softwaretester.info
$ phantomjs screenshot.js "http://softwaretester.info"

Performance measurement with PhantomJS and confess

PhantomJS and confess make it possible to measure your webapplication performance via command-line.

Precondition

Preparation

If your PhantomJS version >= 2.0, phantom.args is deprecated! “TypeError: undefined is not an object” You have to make a quick hack inside the confess.js file.

# add in top of file
var system = require('system');

# replace all
phantom.args
# by
system.args

# change
var a = 0;
# into
var a = 1;

Run the performance measurement

# change to folder with confess.js and config.json
$ cd /path/to/folder

# generation of an appcache manifest
$ phantomjs confess.js <URL> appcache

# run performance measurement
$ phantomjs confess.js <URL> performance

Note: By default the results go to stdout, but you can pipe into a file!

Run your Python Selenium tests headless

This time i show you the headless testing with Selenium WebDriver and PhantomJS. This method can be used for example on continuous integration systems.

Install PhantomJS

Follow the documentation on PhantomJS website or as Mac OS X user simply use Mac Ports.

# on Mac OS X
$ sudo port install PhantomJS

# check version
$ phantomjs --version

Create a tiny test script

#!/usr/bin/env python
import unittest
from selenium import webdriver


class SearchContentOnWebsite(unittest.TestCase):

    def setUp(self):
        # create a new PhantomJS session
        self.driver = webdriver.PhantomJS()
        self.driver.set_window_size(800, 600)
        self.driver.get("http://softwaretester.info")

    def test_search_headline(self):
        title = 'This will fail | - Softwaretester -'
        assert title in self.driver.title

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main(verbosity=2)

Just create a instance of PhantomJS WebDriver and run you tests. That is all! 😉