≡ Menu

Fitnesse Selenium Wrapper

Two powerful tools for communicating requirements from your customers, and testing those requirements, are Fitnesse and Selenium. Fitnesse, a wiki encapsulating the Framework for Integration Tests (aka FIT), enables customers to write sentence-like tests which can be mapped to the underlying system. Selenium drives a browser without all of the fragile mouse coordinate testing you get from a lot of testing tools (ala WinRunner).

While there’s been a lot of good posts on Fitnesse and Selenium, none of them seemed to fit in to exactly what we need, which was a way for our customers to harness the power of Selenium in the acceptance tests they are writing. So, using the DoFixture and the Selenium Remote Control Java API, we were able to hack together a custom Fitnesse fixture which reads surprisingly well.

First, you’ll need to set up Selenium. I’m going to be writing a tutorial on it soon, but basically just download the Selenium Remote Control, unzip it, and start up the server. With the server running, you can write Java code which will make calls to the server and interact with the browser.

Now, onto our tests. We wanted to give our customers the ability to write tests like:

|The user navigates to the URL|http://www.google.com|

|The page has the title|Google|

|The page has an element named|q|

|The page has an element named|btnG|

|The user Types|Cory Foy|in the field named|q|

|The user clicks on the button named|btnG|

|The user closes the browser|

This is the wiki-syntax from Fitnesse, and something our customers are familiar with writing. One of the nice things about the DoFixture in Fitnesse is that it knows how to convert these to java method calls. For example, this:

|The user navigates to the URL|http://www.google.com|

gets mapped to:

public boolean TheUserNavigatesToTheUrl(String url) {}

I’ve put the Fitnesse fixture up for download. You’ll need to compile it and put it on the classpath, along with the Selenium java client jar. To use it, you’ll have to make sure that the SeleniumRunner is the first table in your test, and then initialize it using the Selenium properties. Ideally, you could just move this up to a SetUp method, so your user wouldn’t see it.

|!-com.cornetdesign.fitnesse.SeleniumRunner-!|

|Set server to|localhost|and port to|4444|and browser to|*firefox|and domain to|http://www.google.com|

The above puts the Fitnesse test into Flow mode, and then initializes the Selenium runner to point at localhost:4444 using the firefox browser, and having the URLs go against the domain google.com.

I’m going to be doing some more work with this, so feedback is welcome. I hope to get a good Selenium tutorial up soon.

Comments on this entry are closed.

  • Anonymous September 16, 2006, 6:20 pm

    Looking nice! keep up the nice work.

    I’m new to Fitnesse and have’t used Selenium yet. I look forward to seeing more examples.

    — Rick

  • Anonymous September 18, 2006, 6:30 am

    Although I really like the idea, you’re going to end up with very wordy tests this way. “Clear customer language” does not have to mean “redundant, repetitive language.” As you get more and more customer tests, it is important that they be succinct, so that the test reader can sort out the noise from the thing actually being tested.

    So, for example, I would change “The user navigates to the URL” to be something like “Navigate to”. I would change “|The user Types|Cory Foy|in the field named|q|” to “|type|Cory Foy|in field|q|” These are still just as readable but more succinct.

    — Jeff Nielsen
    Digital Focus

  • Cory Foy September 18, 2006, 6:47 am

    Thanks Jeff. We’ve got a similar discussion going on at the XP list.

    I know we could make them more terse, but they don’t read like good user stories. Most of the customers I’ve dealt with (except the technical ones) don’t mind writing out sentences, as long as they don’t have to do the pipes. In fact, in some industries, they feel duty-bound to be wordy. ;)

    So, I’m trying to find a way to have clear, readable tests that don’t require the user to write a book. I don’t feel like being as terse as you have is quite it, but I’m not positive being as verbose as what I have above is quite it either. I guess I’m just stuck communicating with the customer to see which they like better.

  • Ged Byrne October 18, 2006, 2:13 pm

    Why not add alias functions?

    public boolean navigateTo(String targetUrl) {return theUserNavigatesToTheUrl(targetUrl);}

  • Anonymous May 3, 2007, 11:05 am

    Thanks for the nice post and getting us started Cory.

    While running the application, I landed into these errors. Do you know why? I have scratched my head a lot and couldnt get along any further. Please help. Thanks

    lasspath: C:\Documents and Settings\dsharda\workspace\Fitness\fitlibrary.jar
    classpath: C:\Documents and Settings\dsharda\workspace\Fitness\fitnesse.jar
    classpath: C:\Documents and Settings\dsharda\workspace\Fitness\SeleniumRunner.jar
    classpath: C:\Documents and Settings\dsharda\workspace\Fitness\selenium-java-client-driver-tests.jar
    classpath: C:\Documents and Settings\dsharda\workspace\Fitness\selenium-server.jar
    classpath: C:\Documents and Settings\dsharda\workspace\Fitness\selenium-java-client-driver.jar

    SeleniumRunner
    Set server to Missing method: public TypeOfResult setServerToAndPortToAndBrowserToAndDomainTo(Type1 arg1, Type2 arg2, Type3 arg3, Type4 arg4) { } in class SeleniumRunner localhost and port to 4444 and browser to *firefox and domain to http://www.google.com

    The user navigates to the URL Missing method: public TypeOfResult theUserNavigatesToTheURL(Type1 arg1) { } in class SeleniumRunner http://www.google.com

  • Anonymous May 3, 2007, 7:43 pm

    Got it to work.. Thanks

  • Anonymous May 3, 2007, 7:44 pm

    How can I get the Assert thing working with Fitnesse. I want to know why a particular test failed and with boolean as the return type for a test I can’t get the stack trace.

    Any idea? Thanks-

  • Fred June 1, 2007, 11:25 pm

    Cory,

    I have also been thinking about how to translate what FIT bring to unit testing to
    user interface web testing. So far I did not find any great answer.

    But I do not see myself writing and maintaining 1000 of lines using Fitness script similar to the one from your post..

    Here is the test that you wrote using InCisif.net and C#.

    For now I will stick with that but I will continue to read you excellent blog.

    using ( InCisif.net.Library.Test t = new InCisif.net.Library.Test(Language.CSharp, this) ) {

    Page.URL = @”www.google.com”;
    Page.WaitForPage(@”re:/www.google.com\/$”);

    Page.Control(“q”).Text = @”Cory Foy”;

    Page.Control(“btnG”).Click();
    Page.WaitForPage(@”/search”); // URL:’http://www.google.com/search’

    t.Passed = true;

    }

  • Thahir June 26, 2007, 9:36 am

    I started the selenium server & ran the java program to open google.com, but in the selenium server it gets stuck up at trying to get the page..Would be really grateful if u could help me thru

    [c:\documents and settings\mthahir]java -jar D:\Selenium\server\selenium-server.jar
    application/xhtml+xml
    Jun 26, 2007 7:58:11 PM org.mortbay.http.HttpServer doStart
    INFO: Version Jetty/0.9.0
    Jun 26, 2007 7:58:12 PM org.mortbay.util.Container start
    INFO: Started HttpContext[/,/]
    Jun 26, 2007 7:58:12 PM org.mortbay.util.Container start
    INFO: Started HttpContext[/selenium-server,/selenium-server]
    Jun 26, 2007 7:58:12 PM org.mortbay.util.Container start
    INFO: Started HttpContext[/selenium-server/driver,/selenium-server/driver]
    Jun 26, 2007 7:58:12 PM org.mortbay.http.SocketListener start
    INFO: Started SocketListener on 0.0.0.0:4444
    Jun 26, 2007 7:58:12 PM org.mortbay.util.Container start
    INFO: Started org.mortbay.jetty.Server@4741d6
    Jun 26, 2007 7:58:15 PM org.mortbay.util.FileResource
    INFO: Checking Resource aliases
    GET: cmd=open&1=http%3A%2F%2Fwww.google.com%2Fwebhp

  • Anonymous February 12, 2008, 7:26 pm

    I’m getting the same outcome as the other anonimous poster,”The user navigates to the URL Missing method: public TypeOfResult theUserNavigatesToTheURL(Type1 arg1) { } in class SeleniumRunner” Can you post how to fix this?

    Thanks

  • Anonymous April 7, 2008, 2:33 pm

    Thank you so very much. This was exactly what I needed to make FitNesse work with Selenium!

  • Anonymous May 12, 2008, 8:55 am

    Cory, what about Selenium calling Fitnesse – how does this work? Also, would you know how to pass parameters from Selenium to Fitnesse and vice versa? Thanks.

  • Mariam June 3, 2008, 7:19 am

    While running the application, I landed into these errors.

    Set server to Missing method: public TypeOfResult setServerToAndPortToAndBrowserToAndDomainTo(Type1 arg1, Type2 arg2, Type3 arg3, Type4 arg4) { } in class SeleniumRunner localhost and port to 4444 and browser to *firefox and domain to http://www.google.com

    The user navigates to the URL Missing method: public TypeOfResult theUserNavigatesToTheURL(Type1 arg1) { } in class SeleniumRunner http://www.google.com

  • HariPriya September 9, 2008, 6:31 am

    Hi,

    Please tell me about the Selenium Runner you are mentioning. I dint see this file in the downloaded one.So I have not included that row in the fitnesse table.

    I tried the same example .I have added the external jars of “selenium server.jar” and “selenium-java-client-driver.jar” also I have specified the class definition in the fixture like below

    import com.thoughtworks.selenium.DefaultSelenium;
    import com.thoughtworks.selenium.Selenium;
    import com.thoughtworks.selenium.SeleniumException;

    import fitlibrary.DoFixture;

    But still I am gettig the below error.

    java.lang.NoClassDefFoundError: com/thoughtworks/selenium/Selenium
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at fit.FixtureLoader.loadFixtureClass(FixtureLoader.java:67)
    at fit.FixtureLoader.instantiateFixture(FixtureLoader.java:58)
    at fit.FixtureLoader.instantiateFirstValidFixtureClass(FixtureLoader.java:88)
    at fit.FixtureLoader.disgraceThenLoad(FixtureLoader.java:39)
    at fit.Fixture.loadFixture(Fixture.java:147)
    at fit.Fixture.getLinkedFixtureWithArgs(Fixture.java:138)
    at fit.Fixture.doTables(Fixture.java:73)
    at fit.FitServer.process(FitServer.java:76)
    at fit.FitServer.run(FitServer.java:52)
    at fit.FitServer.main(FitServer.java:43)

    PLease can you help?

    Thanks

  • Anonymous February 12, 2009, 8:33 am

    Getting this error –

    fittest.SeleniumRunner Missing method: public TypeOfResult getFittestDotSeleniumRunner() { } OR: public TypeOfResult fittestDotSeleniumRunner() { } in class fittest.SeleniumRunner
    Set server to Missing method: public TypeOfResult setServerToAndPortToAndBrowserToAndDomainTo(Type1 arg1, Type2 arg2, Type3 arg3, Type4 arg4) { } in class fittest.SeleniumRunner localhost and port to 4444 and browser to *firefox and domain to http://www.google.com

    The user navigates to the URL Missing method: public TypeOfResult theUserNavigatesToTheURL(Type1 arg1) { } in class fittest.SeleniumRunner http://www.google.com

  • tina February 12, 2009, 8:34 am

    I am getting this method missing error still.
    Somebody please suggest, how it works.

  • Shankar.Laggishetti March 24, 2009, 5:30 am

    Hi Cory,

    Nice Post.

    I am new to Fitnesse.

    When i am running test using with the Fitnesse i am getting follwoing errors “Missing methods: public TypeOfResult setServerToAndPortToAndBrowserToAndDomainTo”

    and

    “Missing methods: public TypeOfResult theUserNavigatesToTheURL”.

    please post line by line integration of wrapper with the fitnesse.

  • kishore September 19, 2009, 6:24 am

    Anonymous :
    I’m getting the same outcome as the other anonimous poster,”The user navigates to the URL Missing method: public TypeOfResult theUserNavigatesToTheURL(Type1 arg1) { } in class SeleniumRunner” Can you post how to fix this?
    Thanks