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"

Start with Python and Selenium WebDriver

This introduction should give you some hints about Python and Selenium WebDriver. I will use this in following tutorials as a base.

Preconditions

  • Python installed
  • pip (package manager) installed
  • Editor or IDE installed

Preparation

As first step simply install or upgrade the Selenium package.

# install or upgrade selenium
$ pip install -U selenium

# get information about package
$ pip show selenium

This is a fairly simple process. After the successful command execution you will have the Selenium WebDriver client library on your machine with all that is needed to create automated scripts.

The first script

Now start using the unittest library. The script comments help to describe the code.

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


class SearchContentOnWebsite(unittest.TestCase):
    """define a class that inherits the TestCase class"""

    def setUp(self):
        """perform some tasks at the start of each test"""
        # create a new Firefox session
        self.driver = webdriver.Firefox()
        # wait for a certain amount of time
        self.driver.implicitly_wait(30)
        # maximize browser window
        self.driver.maximize_window()
        # navigate to the start URL
        self.driver.get("http://softwaretester.info")

    def test_search_headline(self):
        """a very simple test case"""
        link_text = 'Modern Status Plugin'
        title = 'Jenkins - Modern Status Plugin | - Softwaretester -'
        # find a element with partial text
        elem = self.driver.find_element_by_partial_link_text(link_text)
        # click element
        elem.click()
        # assert that title have value
        assert title in self.driver.title

    def tearDown(self):
        """method to clean up any initialized values after the test"""
        # close the browser window
        self.driver.close()

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

Run Test

To run the test simple call your script.

./my_first_test.py

# or
python my_first_test.py

Create your own test application

A lot of software testers do have no or less development skills. They also have less skills to use commandline tools and need GUI applications. In addition, the test applications for the respective claims should be easy to use. This guide will show you how to easily deploy software testers the needed test tools. This is just an example, please feel free to expand it!

Precondition

Let`s go

After create a new PyCharm project (with virtualenv), create 2 new empty files (requirements.txt, ShowHeaders.py) and import a icon. You can found icons (*.icns) on iconarchive for free.

application project files

Open the “requirements.txt” file and add Requests library.

requests==2.6.0

Open the “ShowHeader.py” and add the following content.

#!/usr/bin/env python
#  -*- coding: utf-8 -*-
"""
This is a main script

Usage:
    python ShowHeaders.py
"""
import requests
from Tkinter import (Tk, Frame, StringVar, OptionMenu, Button, Entry, Text,
                     END, DISABLED, NORMAL, SUNKEN, E, W)


class ShowHeaders(object):
    """
    ShowHeaders class
    """

    OPTIONS = ["GET", "POST", "PUT", "DELETE"]

    def __init__(self):
        """
        Constructor for Tk GUI
        """
        self.root = Tk()
        self.root.title('Show Headers')
        self.root.configure(bg="light blue")
        self.option = StringVar(self.root)
        self.option.set(self.OPTIONS[0])
        self.methods = None
        self.url = None
        self.response = None
        self.copy = None

    def create_gui(self):
        """
        Create Tk GUI
        """
        self._create_top_frame()
        self._create_middle_frame()
        self._create_bottom_frame()
        self.root.mainloop()

    def close_app(self):
        """
        Close & Quit Application
        """
        self.root.quit()

    def _print_response(self, response_txt):
        """
        Print response
        """
        self.response.config(state=NORMAL)
        self.response.delete(1.0, END)
        self.response.insert(END, response_txt)
        self.response.config(state=DISABLED)

    def _copy_to_clipboard(self):
        """
        Copy to text clipboard
        """
        text = self.response.get("1.0", END)
        self.root.clipboard_clear()
        self.root.clipboard_append(text)

    def _make_request(self):
        """
        Run http request and print
        """
        self.copy.config(state="normal")
        methods = self.option.get()
        url = self.url.get()
        if methods == 'GET':
            req = requests.get(url)
        elif methods == 'POST':
            req = requests.post(url)
        elif methods == 'PUT':
            req = requests.put(url)
        elif methods == 'DELETE':
            req = requests.delete(url)
        else:
            req = dict()
        header = req.headers
        self._print_response(header)

    def _create_top_frame(self):
        """
        Create top frame
        """
        top_frame = Frame(self.root)
        top_frame.grid(row=0, column=0, padx=5, pady=5, sticky=W+E)

        self.methods = OptionMenu(top_frame, self.option, *self.OPTIONS)
        self.methods.config(width=15)
        self.methods.grid(row=0, column=0)

        self.url = Entry(top_frame, width=50)
        self.url.insert(0, "http://")
        self.url.grid(row=0, column=1)

        Button(top_frame, text='Request', command=self._make_request).grid(
            row=0, column=2)

    def _create_middle_frame(self):
        """
        Create middle frame
        """
        middle_frame = Frame(self.root, height=75, bd=1, relief=SUNKEN)
        middle_frame.grid(row=1, column=0, padx=5, pady=5)

        self.response = Text(middle_frame, height=10)
        self.response.config(state=DISABLED)
        self.response.grid(row=1)

    def _create_bottom_frame(self):
        """
        Create bottom frame
        """
        bottom_frame = Frame(self.root)
        bottom_frame.grid(row=2, column=0, padx=5, pady=5, sticky=W+E)

        self.copy = Button(bottom_frame, text="Copy", state=DISABLED,
                           command=self._copy_to_clipboard)
        self.copy.grid(row=0, column=0)

        Button(bottom_frame, text='Quit', command=self.close_app).grid(
            row=0, column=1)


if __name__ == '__main__':
    APP = ShowHeaders()
    APP.create_gui()

For first test, run the application. If there are no issues – open the PyCharm terminal and run the following command.

$ py2applet --make-setup ShowHeaders.py

# or if you use virtualenv
$ /Users/<username>/ShowHeaderEnv/bin/py2applet --make-setup ShowHeaders.py

Now you should see the generated file “setup.py” in the Project. Open the file and add the icon. The content should look like this:

"""
This is a setup.py script generated by py2applet

Usage:
    python setup.py py2app
"""

from setuptools import setup

APP = ['ShowHeaders.py']
DATA_FILES = []
OPTIONS = {'argv_emulation': True, 'iconfile':'header.icns'}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

Now execute the following command to build, for first test.

$ python setup.py py2app -A

After some messages in terminal, your Project should show 2 new folders (build, dist). The alias mode (-A / –alias) instructs py2app to build an application, but it is not portable to other machines! You can open the Application in Finder or from terminal for your tests. If there are changes, just run the build-command again.

$ open dist/ShowHeaders.app

If everything is fine and your Application is ready for ship, run the following command.

# remove build and dist folder
$ rm -fr build/ dist/

# build application
$ python setup.py py2app

Again the Application can be found on folder “dist”. The result should look like this:

example application

Have fun and be creative! Too ship the test application for Windows users, look at py2exe.

Robot Framework and Apache Ant

This tutorial is meant to show how easy you can use Robot Framework with Apache Ant. You can use later the build file for example with Jenkins.

Preconditions

Instructions

My folder structure looks like this:

Project structure

Within the folder “report” all logs and reports should be stored. Inside the folder “testsuite” are all Robot Framework files. The “build.xml” looks like this:

<?xml version="1.0"?>
<project name="RobotFramework" basedir="." default="run">
	<description>
		Simple Apache Ant example for running RobotFramework
	</description>
	
	<property name="suite.dir" location="testsuite" />
	<property name="docs.dir" location="report" />
	
	<!-- set time -->
	<target name="init">
		<tstamp>
			<format property="TODAY_DE" pattern="dd.MMMM.yyyy" locale="de" />
		</tstamp>
	</target>
	
	<!-- delete docs.dir -->
	<target name="clean" depends="init">
		<delete dir="${docs.dir}" />
	</target>
	
	<!-- create docs.dir -->
	<target name="setup" depends="clean">
		<mkdir dir="${docs.dir}" />
	</target>
	
	<!-- running testsuite -->
	<target name="run" depends="setup">
		<echo message="${TODAY_DE}" />
		<exec executable="pybot">
			<arg line="-d ${docs.dir}" />
			<arg value="${suite.dir}" />
		</exec>
	</target>
	
</project>

The content of the build.xml is self-explanatory. Now opening a terminal and run Apache Ant.

# direct on folder simple type ant
$ ant

# you can specify the build file
$ ant -buildfile build.xml

# you can specify the target
$ ant run

 

REST testing with jMeter

Testing RESTful application is very simple with jMeter. In the first part of the tutorial in this series, the basics are shown. As requests can be created and evaluated. The request going to http://httpbin.org.

Preconditions

  • JAVA is installed
  • jMeter is installed

Steps

Create new “Thread-Group” on “Test Plan” (Add – Threads (User) – Thread Group)

jmeter thread group

Now add one “HTTP Request” inside the “Thread Group” (Add – Sampler – HTTP Request)

jmeter http request

Inside the “HTTP Request” we add now a “HTTP Header Manager” (Add – Config Element – HTTP Header Manager). For configuring we add the Name/Value – “Content-Type”/”application/json”.

jmeter http header manager

At the end we add the “View Results Tree” on “Thread Group” (Add – Listener – View Results Tree)

jmeter view results tree

Our first request example will be a “GET”. On HTTP Request we add following values.

  • Server Name or IP: httpbin.org
  • Method: GET
  • Path: /ip
  • Implementation: HttpClient4
  • Follow Redirects: yes
  • Use KeepAlive: yes
jmeter get request

After save we can start the first run. How to see result will show later. Now second request with POST example. For this we modify the HTTP Request with following values.

  • Method: POST
  • Path: /post
  • Send Parameters With the Request: {“firstName”:”harry”;”lastName”:”Hirsch”}
  • Include Equals?: yes
jmeter post request

Now save and run again. On View Results Tree we can check the results for every http request (Sampler results, Request, Response data).

jmeter rest results

For the JSON response, switching from Text to JSON view. The same way can used for PUT, DELETE or other requests.

Robot Framework and Selenium-Grid 2.0

This small tutorial shows, how to run a generic Robot Framework test with Selenium Grid.

Preparation

Steps

Now we create a very simple test

*** Settings ***
Documentation         This is just a tutorial
...
Metadata              VERSION    0.1
Library               Selenium2Library
Suite Setup           Start Browser
Suite Teardown        Close Browser

*** Variables ***
${SERVER}             https://www.google.ch
${BROWSER}            firefox

*** Keywords ***
Start Browser
    [Documentation]   Start firefox browser on Selenium Grid
    Open Browser      ${SERVER}   ${BROWSER}   None    http://127.0.0.1:4444/wd/hub

*** Test Cases ***
Check something
    [Documentation]   Check the page title
    Title Should Be   Google

Now start the Selenium Grid (Hub and Node)

# start the hub (in terminal 1)
$ java -jar selenium-server-standalone-2.44.0.jar -role hub -port 4444 

# start the node (in terminal 2)
$ java -jar selenium-server-standalone-2.44.0.jar -role node -hub http://localhost:4444/grid/register

Note: The actual version for selenium-server-standalone may be different!

Open the browser http://localhost:4444/grid/console and check the node is registered. This step can be skipped, just to be sure.

In the last step we start the test. Open a 3rd terminal, browse to the folder and start the Robot Framework.

# run pybot
$ pybot tutorial.robot

If everything works well, the output should look like this:

================================================================
Tutorial :: This is just a tutorial
================================================================
Check something :: Check the page title                 | PASS |
----------------------------------------------------------------
Tutorial:: This is just a tutorial                      | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
================================================================
Output: /output.xml
Log: /log.html
Report: /report.html

PyCharm and Robot Framework

This tutorial should show, how easy it is to use the Robot Framework with PyCharm. After this small setup you can use PyCharm for your test automation with Robot Framework.

Preparation

Install PyCharm and the Robot Framework.

# check installed modules
$ pip list

# install Robot Framework (if not listed)
$ sudo pip install robotframework

# upgrade to the latest version
$ sudo pip install --upgrade robotframework

# verify installation
$ pybot --version

Configuration of PyCharm

Now start PyCharm and open “Preferences” – “Plugins”. Press “Browse repositories…” button and search for “Intellibot”. Press “Install plugin” button and restart PyCharm.

pycharm intellibot

Now create a new directory “testsuite” with new file named “example.robot” inside and insert the following content.

*** Test Cases ***

Example action log         this is a test

Open “Preferences” – “Tools” – “External Tools” and press “+” button. Insert a value for “Name”, enable checkbox “Open console”, insert “pybot” into Program, “test suite/” into Parameters and select you specific Working directory.

pycharm robotframework

After press “OK” buttons, go to menu “Tools” – “External Tools” and select your given name. The output should show something like this:

/usr/local/bin/pybot testsuite/
=============================================================
Testsuite
=============================================================
Testsuite.Example
=============================================================
Example action                                       | PASS |
-------------------------------------------------------------
Testsuite.Example                                    | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
=============================================================
Testsuite                                            | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
=============================================================
Output: /output.xml
Log: /log.html
Report: /report.html

Process finished with exit code 0

Extended

In the next steps we create a first very simple test automation. For this we need to install the “selenium2library”.

# install package
$ sudo pip install robotframework-selenium2library

Now we create inside the “testsuite” directory a file called “1st_test.robot” with following content.

*** Settings ***
Documentation           This is a simple test with Robot Framework
Library                 Selenium2Library

*** Variables ***
${SERVER}               http://google.com
${BROWSER}              Firefox
${DELAY}                0

*** Keywords ***
Open Browser To Login Page
   Open Browser         ${SERVER}   ${BROWSER}
   Maximize Browser Window
   Set Selenium Speed   ${DELAY}

*** Test Cases ***
Valid Login Open Browser To Login Page
[Teardown].             Close Browser

After running the output should look like this:

/usr/local/bin/pybot testsuite/
=============================================================
Testsuite
=============================================================
Testsuite.1St Test :: This is a simple test with Robot Framework
=============================================================
Valid Login                                          | PASS |
-------------------------------------------------------------
Testsuite.1St Test :: This is a simple test with Robot Framework      | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
=============================================================
Testsuite.Example
=============================================================
Example action                                       | PASS |
-------------------------------------------------------------
Testsuite.Example                                    | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
=============================================================
Testsuite                                            | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
=============================================================
Output: /output.xml
Log: /log.html
Report: /report.html

Process finished with exit code 0

Small helper for iOS automated test 2

The second part of this small series, it shows how to obtaining device property informations.

Helper

var Device = {
  isIPhone: function() {
    return this.target().model().match("iPhone");
  },
  isIPad: function() {
    return this.target().model().match("iPad");
  },
  isName: function() {
    return this.target().name();
  },
  isSystemName: function() {
    return this.target().systemName();
  },
  isSystemVersion: function() {
    return this.target().systemVersion();
  },
  target: function() {
    return UIATarget.localTarget();
  }
};

Example

var message = Device.isName();
UIALogger.logMessage("Name: " + message);

var message = Device.isSystemName();
UIALogger.logMessage("SystemName: " + message);

var message = Device.isSystemVersion(); UIALogger.logMessage("SystemVersion: " + message);

if (!Device.isIPad()) {
  throw new Error("Test suite only works on iPad");
}