Selenium Webdriver and Jenkins

This post has been hold for quite long time because several reasons: there are bunch of articles covering this setup, there are a lot of questions posted in Q&A site on the similar topic. But then I decided to post it with hope it will help other who face similar problem with selenium web driver.

Version

Firefox version versus webdriver version (selenium-standalone-server.jar) is somehow overlapping each other in a way that firefox version increases every now and then and most of the time our firefox automatic update is enabled, while even the newest web driver does not support the newest firefox. So, just take this recipe: Selenium server 2.31 only support firefox up to  version 17.0. I don’t really know what could it be with the older version of both, most likely it will work.

Jenkins Master Setup

Normally I have several jenkins’ executor (slave/node) to run specific task. Especially for web automation test, I use one dedicated node just to run the tied jenkins’ job only. Following is the setup for the slave machine:

OS      : Ubuntu 12.04.1 LTS
X       : Xvfb
Firefox : Firefox 16.0
Java    : 1.7.0_15
          OpenJDK Runtime Environment (IcedTea7 2.3.7) (7u15-2.3.7-0ubuntu1~12.04.1)
          OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

Here is the Jenkins’ slave setup:

jenkins-slave

It’s also important to take note on the slave launch method, after some consideration and learning from experiences, I choose to launch slave agent via SSH. I used to use root account for this, but I found out somehow firefox has an issue whenever executed by root. I don’t think that this is known problem, so I choose to use non-root user for this purpose (jenkins).

launch-slave

Jenkins Slave Setup

On the slave you need to have `jenkins` user with /var/lib/jenkins as its HOME directory.

# adduser --home /var/lib/jenkins --disabled-password jenkins
# chown -R jenkins:jenkins /var/lib/jenkins

SSH key pair also needed and make sure that master’s public key is put inside slave’s authorized_keys. Also you need to install ssh-askpass

# ssh-keygen
# cat /path/to/master_public_key >> /var/lib/jenkins/.ssh/authorized_keys
# sudo apt-get install ssh-askpass

As you may see, DISPLAY is set to :1, this is related with the display used by Xvfb. This is how Xvfb is started:

/usr/bin/Xvfb :1 -screen 0 1024x768x24

There is also a little note that is important if you use ThoughtWorks’s Twist, you will need to define the hostname in the host file.

# /etc/hosts
127.0.0.1       localhost qa-auto-1 qa-auto-1.localfoo.com

From my trials, I found some keys to make the testing setup stable enough for the long run:

  1. Make sure firefox version is not updated unless selenium server is updated, and make sure the version mix-match for compatibility. For my own setup, I stick with Firefox 16.0 and Selenium Server 2.31
  2. Do not execute testing job with root account. There is either known or unknown problem when firefox is executed with root.
  3. In particular if you use Twist, you will need to define your hostname to your host file.
  4. Make sure X is always available, I put a cron job to monitor whether X is running or not, then do the task respectively.
Advertisements

List of USB Wireless Compatible with Linux + Support Master Mode

I have been looking for USB wireless adapter that works with master mode (AP) and it’s really a PITA job. The full list of supported devices available here: http://linuxwireless.org/en/users/Devices/USB

BUT, it’s really difficult for me to find the device, some of them are outdated devices and most of them are not available in the market, and to check whether it supports master mode or not, I have to check it with Linux utilities (iwconfig). Here is what I found from Google:

http://home.comcast.net/~tomhorsley/hardware/rtl8192cu/rtl8192cu.html

http://www.amazon.com/gp/product/B00333AWTA

http://rt2x00.serialmonkey.com/wiki/index.php/Hardware

Finally I found one with very cheap price (less than USD 10) which is TP-LINK WN422G with wireless-compat driver (ath9k_htc)

http://linuxwireless.org/en/users/Drivers/ath9k_htc/devices

This device can work with hostapd. I use this device with ARM board (Samsung SMDK6410), running Linux 2.6.28

Multicall Binary

Jika anda pernah menggunakan busybox, pasti anda paham apa itu multicall binary. Busybox adalah contoh dari multicall binary, mencakup hampir semua perintah dasar shell. Definisi kasarnya adalah sebuah binary yang dapat dipanggil dengan berbagai nama. Hal ini dapat dilakukan dengan memanipulasi argv[0] yang mana menunjuk pada program name. Misalkan:

int main(int argc, char **argv)
{
        printf("nama program: %s\n", argv[0]);
        return 0;
}

Kemudian kita panggil binary dari kode di atas:

./a.out
nama program: ./a.out

Sama halnya dengan:

ln -s a.out app
./app
nama program: ./app

Saya mencoba untuk membuat sebuah multicall binary sederhana dengan konsep di atas, yaitu dengan memanipulasi argv[0]. Setiap kali ditemukan argv[0] yang sesuai maka fungsi bersangkutan akan dipanggil. Untuk melakukannya kita gunakan array yang berisi pointer to function yang nantinya dipanggil menyesuaikan dengan isi argv[0].

/* Applet struct */
struct applet {
        int id;
        char *name;
        void (*app) (void);
};
/* Array of pointer to function */
static void (*applet_callback[]) (void) = { applet0, applet1, applet2 };

/* Array of applet name */
const char *applets[] = { "applet0", "applet1", "applet2" };

Tinggal kita terapkan apakah isi argv[0] sama dengan salah satu dari isi array applets[], dapatkan indexnya untuk mengisi applet->app dengan applet_callback[index]. Jangan lupa implementasikan masing2 fungsi dalam applet_callback[].

if (strcmp(applets[asize], foo->name) == 0) {
       appid = asize;
       foo->app = applet_callback[asize];
       return appid;
}

Tinggal tambahkan perintah untuk menjalankan:

       foo->app();

Untuk mengetesnya:

gcc applet.c -o applet
ln -s applet applet0
ln -s applet applet1
ln -s applet applet2
./applet2
calling: ./applet2
get applet2 at 2
Applet2 is running!

Kode tersedia di:
HTTP: https://github.com/ruckuus/multi
Git: git://github.com/ruckuus/multi.git

fortune game

Q: How many gradual (sorry, that’s supposed to be “graduate”) students
does it take to screw in a light bulb?
A: “I’m afraid we don’t know, but make my stipend tax-free, give my
advisor a $30,000 grant of the taxpayer’s money, and I’m sure he
can tell me how to do the gruntwork for him so he can take the
credit for answering this incredibly vital question.”

Lindent – amazing script for lazy C coder

For you a lazy C coder, sometimes indentation could be a big mess when you only think about code’s performance and not so into a cosmetic and style. Anyway, I was in that time too, I never thought about the importance of style when I wrote a code until I have to review someone’s code. It’s crappy and PITA, it ended up by me writing the whole code from scratch.

Thanks to kernel source script: Lindent now that cosmetic stuff is over, you can just write the code your way, and in the end call this script to make your code better and readable, and the most important is: it conforms Linux CodingStyle ;-).

Here we go, you can get it from Linux source in script directory: linux-source/scripts/Lindent. Or you can make a leftover from the snippet below:

1#!/bin/sh
   2PARAM="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1"
   3RES=`indent --version`
   4V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
   5V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
   6V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
   7if [ $V1 -gt 2 ]; then
   8  PARAM="$PARAM -il0"
   9elif [ $V1 -eq 2 ]; then
  10  if [ $V2 -gt 2 ]; then
  11    PARAM="$PARAM -il0";
  12  elif [ $V2 -eq 2 ]; then
  13    if [ $V3 -ge 10 ]; then
  14      PARAM="$PARAM -il0"
  15    fi
  16  fi
  17fi
  18indent $PARAM "$@"
  19

You can use it as follow:

$ /path/to/Lindent source.c

Consider following images:

1. before

2. After

Lindent uses the features of GNU indent. A tool to change the appearance of a C program by inserting or deleting whitespace.

Vim – entering special character

It’s been a question for me for years, but usually I ignore it. Sometimes, I want to put a special character on my code, for example; a copyright symbol (©) or registered sign (®) or a latin character, or other. Actually it is quiet simple to do using Vim.

First thing to know is RFC1345: Character Mnemonics and Character Sets. You need to know the character mnemonic, then how to put it on your code. Vim provides :digraph. Simply open Vim and type :digraph, you should find a table of special characters which are available in Vim. There are several way of using :digraph, in INSERT mode you can use CTRL+K followed by _two letter combination_, or :set digraph (:set dg), or by entering character value after pressing CTRL+V.

Consider this image:

Vim :digraph

There are three columns described as follow:

1. magenta block (#1): SH, D1, Nb, NH, TS ….

2. green block (#2): ^A, ^Q, #, , , …

3. orange block (#3): 1, 17, 35, 131, 147 …

The first column (#1) represent two letter combination to show the special character in digraph after pressing CTRL+K

The second column (#2) is the special character you want to type

The third columnd (#3) is the character’s decimal value based on RFC1345

See what are the value you need related with REGISTERED SIGN from :digraph extract

Rg  ® 174

So, you can proceed by:

1. CTRL+K Rg

2. CTRL+V 174

3. R <BS> g

For option #3, this can only work when you :set digraph (or :set dg)

<BS> is CTRL+H in Vim

For complete reference, you can see Vim: digraph documentation