Testing a web-app with Selenium (part1)

Today I want to deal with application testing.
I have split my post into several parts.
The first part deals with the definition of a simple test for an existing application already installed (e.g. in a test environment).
The second part is about how to perform integration testing during the build with Maven.

The problem: how to create automatic repetible integration tests for web apps?

The solution: write  test cases using Selenium.

Let’s start with a simple web-app. Notice that at this level the language used to write it is not relevant.
In this case I used wicket as ajax framework and maven to build it.
Our web-app is simple calculator performing a sum between two number. It’s composed by a panel with two text-box, a ajax button and a label for the result. It’s deployed on JBoss.

 

Our automatic test has to fill the two text boxes, click the “Add” button and assert the correct result.
Moreover, we can assert if all the widgets are presents on the user interface as well.
There are several ways to create an automatic test with Selenium:

  • using Selenium IDE (a powerful plug-in for Firefox) to record interactions with a browser
  • using Selenium WebDriver  to drive a browser programatically

Usually, for the beginners I suggest to start using SeleniumIDE to record a specific test case. After that  it’s always possible to convert the test case recorded in a specific language (JAVA, C#, Python) for use it in Selenium WebDriver.

Let’s start with the Selenium IDE:
To install it take a look at the IDE documentation (http://seleniumhq.org/projects/ide/).
Now, open Firefox at the application url. From the Firefox menù click on Tools -> Selenium IDE:

just click on the red button on the command bar and we are ready to record the test steps:

  1. in the first text box write the value “1”
  2. in the second write the value “5”
  3. click ADD

 

Notice in the IDE  the steps recorded. As last step we have to define the assert of correct result.
To do that, right click on the label containig the result –> click on Show All Available Commands –> wait for text present 6

Done! This is our first test case….
Save it with the name “TestSum”  and close both Firefox and Selenium.
Reopening Firefox (and Selenium), we load the test case to run it clicking on run on the command bar. Notice that Selenium open automatically the correct page, fills the fields and assert the result. If all is ok, you will see a green strip, otherwise a red one.

Now we have a test case that can be run on several environments (dev, test, pre-production…) just changing the Base URL on Selenium IDE.

With the same process we can record a test case to assert the components on our user interface. More test cases saved together form a Test Suite. In other words, I can define a test suite loading more test cases and save it together with the SeleniumIDE.

How to convert the test case in JAVA?
After we have recorded our test case, we want to convert it in java to perform more complex actions.
The first thing to do is export the test case directly from SeleniumIDE.
I export it as Java /JUnit4/Web driver.  I get in this way a simple java file that i import in an aclipse project.

This is the snippet:

public class TestSum {
 private WebDriver driver;
 private String baseUrl;
 private StringBuffer verificationErrors = new StringBuffer();
 @Before
 public void setUp() throws Exception {
  driver = new FirefoxDriver();
  baseUrl = "http://localhost:8080/";
  driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
 }
 @Test
 public void testSum() throws Exception {
  driver.get(baseUrl + "/");
  driver.findElement(By.xpath("//td/input")).clear();
  driver.findElement(By.xpath("//td/input")).sendKeys("1");
  driver.findElement(By.xpath("//td[2]/input")).clear();
  driver.findElement(By.xpath("//td[2]/input")).sendKeys("5");
  driver.findElement(By.xpath("//tr[2]/td/input")).click();
  for (int second = 0;; second++) {
   if (second >= 60) fail("timeout");
   try { if (driver.findElement(By.cssSelector("BODY")).getText().matches("^[sS]*6[sS]*$")) break; } catch (Exception e) {}
   Thread.sleep(1000);
  }
}

This is a simple JUnit class that uses WebDriver to drive the browser.
We import this in an eclipse project and we download the libs to compile it from http://seleniumhq.org/download/
Since we deal with a java class we have to download the java libs.

Let’s a look at the code: In this case the browser is Firefox, since i’m using  a FirefoxDriver, but you can choose more driver (InternetExplorerDriver, ChromeDriver and so on… ) The unique thing to check is your command path has to contain the path to the executable file of your browser.
Each element on the page is find by using XPath.

But what’s happen if we attempt to run this class?

As if by magic Selenium WEBDriver opens automatically Firefox and executes the steps of the test!!!
So we have find a way to control a browser programmatically. This opens a wide scenario.
For istance, use the power of a language as Java to define several actions and define articulated tests, schedule integration test overnight on different environments… There is no limit!!

But this step is very important for the second part of this post. Since we have a JUnit class we can think to execute it during the build phase with maven!
But this will be trated in the near future….
That’s all for now.

Carmine.

Wicket – How to replace a panel with Ajax

Today I’d like to deal with a common problem in wicket application. How to replace dinamically a panel. Let’s start…

The problem:
You have a Radio Choice with two buttons, when you click on the first button, the panel1  is diplayed, when you click on the second one, the panel2 is displayed in place of the last one and so on…

The solution: I write two different html files for the two panels: panel1.html and panel2.html.

<wicket:panel>
 this is the panel 1
 </wicket:panel>
<wicket:panel>
 this is the panel 2
 </wicket:panel>

The java class for each panel looks like this:

public class Panel1 extends Panel{
    public Panel2(String id) {
       super(id);
       //write other code here...
    }
}

Now we can start with the parent component wich will contain the panels and the radio component.
The parent component can be a Page or another panel. For this example it is a wicket page. Here is the html code:

<html>
    <head>
        <title>Replace Panel example</title>
    </head>
    <body>
        <form wicket:id="form">
          <span wicket:id="rChoice"></span>
          <span wicket:id="replacedPanel"></span>
        </form>
    </body>
</html>

Under the tag form we have two components, the radio choice and a panel. This panel will be replaced each time the user changes the radio selection.

To do that using Ajax, we have to attach a behaviour to the radio choice component.
Let’s take a look at the java code…

public class HomePage extends WebPage {
    private Panel replacedPanel;
    public HomePage(final PageParameters parameters) {
        List<String> choices = new ArrayList<String>();
        choices.add("panel1");
        choices.add("panel2");
        final RadioChoice<String> rChoice = new RadioChoice<String>("rChoice");
        rChoice.setModel(new Model<String>(selectedPanel));
        rChoice.setChoices(choices);
        rChoice.add(new AjaxFormChoiceComponentUpdatingBehavior() {
              @Override
              protected void onUpdate(AjaxRequestTarget target) {
                  Panel newPanel = null;
                  if ("panel1".equals(rChoice.getModelObject())){
                      newPanel = new Panel1("replacedPanel");
                  }else{
                      newPanel = new Panel2("replacedPanel");
                  }
                  newPanel.setOutputMarkupId(true);
                  replacedPanel.replaceWith(newPanel);
                  target.addComponent(newPanel);
                  replacedPanel = newPanel;  
              }
        });
        //this shows the panel1 when you load for the first time the page
        replacedPanel = new Panel1("replacedPanel");
        replacedPanel.setOutputMarkupId(true);
        Form<String> form = new Form<String>("form");
        form.add(rChoice);
        form.add(replacedPanel);
        this.add(form);       
    }
}

Finished!
As you can see, the most important thing is that the two panels should have the same id (in this case is replacedPanel).
This is a general example, maybe the way to create the panels in the onUpdate method is not elegant but it’s out of scope from this example.

That’s all for now.
Carmine