Thursday 30 October 2008

New look - Same Old Blog

I was becoming frequently frustrated by the design constraints of the template i had chosen. Whenever i needed to share long lines of code (FitNesse Mark-up) they would wrap or truncate on screen.

I have solved this by using a very simple layout (all of the articles are still here) and i have implemented dp.SyntaxHighlighter by Alex Gorbatchev

If your not seeing pretty "HighLighted" code snips like this:



you are probably blocking the functionality with an AdBlocker or some such.

Wednesday 29 October 2008

Proxy chaining with selenium

Proxy chaining with selenium was the topic of a recent conversation with a colleague,he wanted to know more about proxy chaining and selenium, this has lead me to write this up. Again this was an issue we ran into early on with FitNesse and selenium , and its something we are currently tackling with Twist.

Selenium uses a proxy.pac files to configure the browser's proxy configuration.

An example selenium proxy.pac:


function FindProxyForURL(url, host) {
if(shExpMatch(url, '/selenium-server/')) {
return 'PROXY localhost:4444; DIRECT'
}
}


In this example the browser will automatically forward any requests containing "/selenium-server/" to the selenium server however all other requests are un proxied and go DIRECT to the requested host.

We work behind a corporate proxy, so we need to be able to send request via the proxy, buy not for all the hosts.

We are using Selenium-RC and we specify some proxy settings on the command line at start-up:


java -Dhttp.proxyHost=proxy.ourdomain.dom -Dhttp.proxyPort=8080 -Dhttp.nonProxyHosts=*dev.ourdomain.dom*^|*qa.ourdomain.dom*^|*staging.ourdomain.dom


when you use start Selenium-RC in this way it generates a proxy.pac file like this:


function FindProxyForURL(url, host) {
return 'PROXY localhost:4444; PROXY proxy.ourdomain.dom:8080';
}



The problem my colleague faced was that no matter what he put on the command line, the browser wasn't honouring his proxy configuration, or so he thought.

The selenium documentation suggest that the way we invoke selenium creates a proxy chain, but this isn't the case, if you look at the proxy.pac file selenium generated it just creates a fail-over chain, where the browser will try and use Selenium RC as the proxy and if it fails it will try and use the proxy you specified on the command line. bugger.

But fear not, there is an additional command line parameter that can be invoked (like a magic incantation) when starting Selenium-RC, its -avoidProxy:


java -Dhttp.proxyHost=proxy.ourdomain.dom -Dhttp.proxyPort=8080 -Dhttp.nonProxyHosts=*dev.ourdomain.dom*^|*qa.ourdomain.dom*^|*staging.ourdomain.dom -jar selenium-server.jar -avoidProxy

Adding the -avoidProxy flag, causes Selenium-RC to generate a proxy.pac file like this:


function FindProxyForURL(url, host) {
if(shExpMatch(url, '*/selenium-server/*')) {
return 'PROXY localhost:4444; PROXY proxy.ourdomain.dom:8080';
} else if (shExpMatch(host, '*dev.ourdomain.dom*')) {
return 'DIRECT';
} else if (shExpMatch(host, '*qa.ourdomain.dom*')) {
return 'DIRECT';
} else if (shExpMatch(host, '*staging.ourdomain.dom*')) {
return 'DIRECT';
} else {
return 'PROXY proxy.ourdomain.dom:8080';
}
}


What this does is use selenium for anything that has /selenium-server/ in the url, else it uses the corporate proxy, unless the host is one of the ones specified in which case it goes direct to that host. Eureka!

Well almost. Enter the same origin policy.

Back to my colleague. He was using *chrome in his tests (note this has nothing to do with google chrome, its firefox but with more schwartz) and if you use one of these "experimental browsers" as Selenium calls them, (*chrome, *iehta) then you need to set your browser's proxy settings manually and just specify the path to your browser as if it were an unsupported browser.

For example, you can launch Firefox with a custom configuration like this:

*custom c:\Program Files\Mozilla Firefox\firefox.exe


When the browser is started like this you have to manually configure the proxy settings to use Selenium Server as a proxy. This just means opening the browser preferences and specifying "localhost:4444" as the HTTP proxy.

I have also used the experimental browser *pifirefox thats proxy inject firefox with good results.

FitNesse and User Authentication

So i have a need to secure our FitNesse instance. FitNesse has built in security, and i have begun to look at that more closely, I'm really only posting this here to serve as an aide mémoire. I will update the post as i progress with the topic.

As described on http://fitnesse.org/FitNesse.StartingAndStoppingFitNesse

To start FitNesse with security enabled and get the username and password form a
text file called password.txt



To create a file called password.txt and add a user into the file.


java -cp fitnesse.jar fitnesse.authentication.Password -f password.txt $FITNESSE_USERNAME

It is usual to use your login id as $FITNESSE_USERNAME.
This would allow you to map the environment variables $LOGNAME or $USER on UNIX or
%USERNAME% under Windows to the FitNesse username.

For stopping fitnesse from command-line when authentication has been enabled:

java -cp fitnesse.jar fitnesse.Shutdown [...more-options] -c $FITNESSE_USERNAME $PASSWORD

Wednesday 8 October 2008

Getting started with FitNesse

A few other colleagues have been trying FitNesse, and hitting the same problems we did.

Lets be frank, the documentation that comes with FitNesse inst great for a beginner, so i have written a brief "how to" (see below) that should get you up and running.

This isn't a step by step hold your hands tutorial (and i haven't found one on the internet either), it assumes you have some level of technical Schwartz and i assume you are using windows (if you are using linux, you should be able to translate without problem). I am alos talking about testing in java here, i wont be covering the .NET tests.

Some Handy Links:

The guy (gojko) who wrote WebTest and Dbfit fixtures, writes a blog which contains a wealth of info.

The Webtest Reference is a must read if you are going to use that fixture, but it is better to print out and pin up.

Steps to create your first test suite.



Installing:

Do you have java installed?
FitNesse is written in Java so you need to have Java installed on your PC to be able to use Fitnesse. If you don't know if you have Java installed, open a command prompt, and tytpe the following

java -version


If you have java installed you should see a message similar to


H:\>java -version
java version "1.5.0_15"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_15-b04)
Java HotSpot(TM) Client VM (build 1.5.0_15-b04, mixed mode)


it doesn't matter too much if the message isn't exactly the same, but if you get the following message


'java' is not recognized as an internal or external command,
operable program or batch file.


then you don't have java installed (or you might have but its not in your path, either way fitnesse isn't going to run until java works for you).


The download of fitnesse will give you a zip file fitnesse.zip.
You should unpack it anywhere you like. But c:\ would be best. if you extract it with folder names it will create a fitnesse directory for you.
Go to that directory and double click on run.bat
You should get a message saying that FitNesse started.
You can then start up your browser and go to http://localhost

Note: when you clicked on the run.bat you have got a warning from windows firewall you should allow or unblock fitnesse as it runs a webserver so it needs to have access.

If you get an error, you may have a web server running on your machine already, using port 80. If this is the case you can specify a different port for fitnesse to run on, like 8080, you can achieve this by going to the fitnesse directory and typing:

java -cp fitnesse.jar fitnesse.Fitnesse -p 8080


Then navigate to it in your web browser. (http://127.0.0.1:8080/)

if this works for you, simple edit the run.bat file and add your port preference in there.

Beefing it up

We now need to install the webfixture. This is the thing that will save us from having to write java code, its taxonomy is also a little warmer than raw selenese.

visit http://www.fitnesse.info/webtest and download the java binaries only package. It will be a jar file.

once downloaded you need to navigate to your fitnesse folder, again i'm assuming its c:\fitnesse and create a new folder in there called lib

inside lib place the downloaded webfixture jar file.

Now get a copy of selenium from http://selenium-rc.seleniumhq.org/download.jsp

i should point out here that i still use version 092 because there are a few flaky things with the newer versions that could leave you pulling out your hair.

Again, place the jar ....

Okay, so i should mention here that if you are behind a proxy, you need to specify that in your selenium start up command.
Creating a test:

Now you have fitnesse up and running you can browse its pages. As you can see there is some content in there already.

To create a new test suite just type the name of the suite in CamelCase in the address bar your browser, e.g lets say i'm going to call my suite MyFirstSuite, i would type
http://127.0.0.1:8080/MyFirstSuite

into the address bar of my browser.

Fitnesse will tell you the page doesn’t exist and give you the option of creating it (the newer version just gives you the edit window, in which case just paste in the path info below).

Before we can write any tests we have to tell fitnesse where we will be storing our libraries by putting the path information into the suite page. In this example I assume you are putting all your jars (selenium, webtest, dbfit) into a folder called lib inside the fitnesse folder.

In the newly created page (type into the edit box) i would type:

!path lib\*.jar


Then i add the fitnesse wiki mark-up command to generate a contents list automatically (this is just me being lazy).

!contents -R


and now save the page (click the save button).

Note: If you want your SetUp and TearDown pages to be collapsed on your test pages you can define the variables:


!define COLLAPSE_SETUP {true}
!define COLLAPSE_TEARDOWN {true}

in the same page too. If you dont know what that means, just move on, dont worry.


Now we have a suite page we need to tell fitnesse that the page is to be treated as a suite. Click the properties button on the left menu. If the properties button is not available on the left menu, then type ?properties at the end of the url in your browser:

http://127.0.0.1:8080/MyFirstSuite?properties


From within the properties page make sure the "suite" checkbox is checked and uncheck the buttons you don’t want to appear in your left hand menu (I never use the files, refactor, search or versions button, so I turn these off but I enable edit if its not already).

Now we need to create the setup and teardown pages for our suite, again we can just type the names at the end of the url in the browser preceded with a '.' period:

http://127.0.0.1:8080/MyFirstSuite.SetUp


Within the SetUp page we declare the fixture we are using for the test, e.g the WebTest fixture

!|com.neuri.webfixture.WebTest|


The exclamation mark tells the wiki not to parse the text in the cell, otherwise is would look for a page called WebTest and think you want to create that page.

You can then put the startup command for selenium here, so for webtest (refer to the reference you printed out above) we use:


|Start Browser|firefox|With Selenium Console On|localhost|At Port|4444|And Scripts At|http://www.bbc.co.uk/|

Note: you would substitute the values for the selenium console (localhost) and its port (4444) depending on what machine you are driving and how you set selenium up. Here I'm assuming you are running the selenium server on your own machine, and it started on port 4444 (the default). But if you have a bit of savvy you should have just realise that you can drive any selenium instance remotely.

You can now save the SetUp page and create the TearDown page in the same way as we created the SetUp page, by typing the page name into the browser:

http://127.0.0.1:8080/MyFirstSuite.TearDown


We only need to put one thing in here, the instruction to shutdown the browser we opened in the SetUp page. again refer to the reference.

|shutdown browser|


Okay, now we have an empty suite.

Ok. Now lets create the test page, in the same way we created the other pages above, by typing the url:

http://127.0.0.1:8080/MyFirstSuite.TestOne


In here we will add a basic test using the WebTest reference to guide us:

Navigate to a URL during the test (change active page)
|user opens url|http://www.bbc.co.uk/radio2|


Check that the page loads fully within given time (use after user opens url)
|page reloads in less than|10|seconds|


Check current browser URL
|page url is|http://www.bbc.co.uk/radio2/|


Check that page contains some text (regardless of whether text is visible or not)
|element|title|contains text|BBC - Radio 2 - Home|


Save the page.


Edit the pages properties, either by the properties button on the left, or (if the button isn't available) by typing ?properties at the end of the url in the browsers address bar:

http://127.0.0.1:8080/MyFirstSuite.TestOne?properties


You can select the option you want, but make sure "Suite" is not checked, and "Test" is checked. Save the page.

You should now find that your test has the SetUp page and TearDown page included.

If selenium is running you should be able to run the test by clicking "test" on the menu.

There you have it, your first test suite. Try now to add TestTwo to your test suite.

Tuesday 7 October 2008

Connecting to Oracle Grid with DbFit

While there is a good deal of info on the DbFit website, there is little about connecting to Oracle databases. The examples given didn't help us at all because we used two nodes in our grid, and we have to give both of them in our connection string (if one node doesn't respond the test will use the other).


!|Connect|(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=node1.grid.domain.net)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=node2.grid.domain.net)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=WEB1_DEFAULT_SERVICE)))| UserName | PassWord |

As you can see you can end up with a very long row in your table, but it does connect.

Using WebTest & DbFit together

If you are testing a web application, there is a good chance that you will need to manipulate or verify some data in a database as part of your testing of the front end application.

It would seem obvious to use DbFit and WebTest on the same test, however you should be aware of a few things.

WebTest is a DoFixture, and DbFit can work in two modes, flow or standalone, you will need to use the standalone mode of DbFit when using DbFit with another fixture..

When creating the SetUp page for the suite of tests add the fixtures like this:


!|com.neuri.webfixture.WebTest|
!|import|
|dbfit.fixture|
!|DatabaseEnvironment|sqlserver|
|Connect|server\SQLEXPRESS|FitNesseUser|Password|TestDB|


Note that there isn't a gap between DatabaseEnvironment and Connect, they must be in the same table

You can also connect to DbFit with the Connect table.

Also remember that since you're using standalone mode of DbFit, it wont rollback or commit, so you will need to use the following tables to commit or rollback transactions:


!|DatabaseEnvironment|
|Commit|



!|DatabaseEnvironment|
|Rollback|


We use the WebTest fixture and DbFit together and it works very well for us. However we have also extended WebTest to include some SQL features in WebTest that allow us to do simple SELECTS and use the output to verify what should be on screen without breaking the flow of the test.

Monday 6 October 2008

I Hate FitNesse / Fitnesse Rocks!


I want you to know that i have a love hate relationship with fitnesse.

I have been using it for several months now and sometimes i really hate it; i still use it and advocate its use, but i still hate it. Tim Ottinger summed up using FitNesse really well over on the FitNesse group (yahoo) . He said that Using Fitnesse is not unlike trying to teach a dog to sing. Its not that the dog is a bad singer, its simply a miracle that it can sing at all.

And its true. FitNesse is not a great wiki, but it does do wiki. It doesn't work very well in CI, but it can be integrated into CI. It has its own versioning that isn't great (millions of zip files), but it can be versioned traditionally (using SVN or CVS). It doesn't have any metrics (test execution over time, defects, test coverage), but you can get those through CI or integration with another tool (we are experimenting with integration into Quality Center [sic]).

There is also the big issue of user management. There several authentication methods supported by FitNesse:

  1. No authentication (default), anybody can do any thing!
  2. UserPassword: Defines one user and its password on fitnesse start: ... -a userA:passworA
  3. PasswordFile: For multiple users, read once on fitnesse start, so adding new users requires a restart ffs.
  4. LinuxPAM plugin: Use PAM to access Linux user passwords, requires a plugin.
  5. Provide your own AuthenticatorClass as plugin.
Given a choice i'd opt for the PasswordFile mode but then administration becomes tiresome.

For more info on user management checkout: