ICE09 . playing with java, scala, groovy and spring .

Playing with Spring

Archive for July, 2010

Quick Tip: Extending WebDriver to react on stopwords

Posted by ice09 on July 18, 2010

The requirement

Happily using WebDriver for some time now, I realized that it makes sense to intercept each call that changes the page source in a way that certain “stopwords”, eg. “exception”, “error”, etc. cause an immediate exception. This is useful if you want to be sure that in a complex test case an exception will never occur. Otherwise, you would have to manually check for it each time the page source is altered.

The problem

I wanted to use the ProxyBeanFactory for this requirement, since it seemed the least compromising way of manipulating the calls to the actual WebDriver. However, I realized that I would have to use AspectJ for this, since calls to private/protected methods inside the bean itself cannot be intercepted by proxies. This is necessary to intercept the call to the method sendMessage, which is used by WebDriver and WebElement for methods which actually change the page source (which makes sense, since this method actually communicates with the plugin via Commands).

The solution

I decided not to use proxies, but just to subclass the FireFoxWebDriver with my own one, which just overwrites the “sendMessage” method. That’s it, the code is as follows.

The Spring config

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="de.demo.proxy"/>

	<util:list id="stopwords">
    	<value>exception</value>
    	<value>Comment</value>
	</util:list>
    
</beans>

The new WebDriver

package de.demo.proxy;

import java.util.List;

import javax.annotation.Resource;

import org.openqa.selenium.firefox.Command;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.springframework.stereotype.Component;

@Component
public class InterceptedFireFoxDriver extends FirefoxDriver {
	
	@Resource(name="stopwords")
	private List<String> stopwords;
	
	@Override
	protected String sendMessage(Class<? extends RuntimeException> throwOnFailure, Command command) {
		String result = super.sendMessage(throwOnFailure, command);
		// avoid endless recursion, sendMessage... is called by getPageSource as well
		if (command.getCommandName().equals("getPageSource")) {
	        return result;
		}
		String content = super.getPageSource();
		// might be null due to initialization issues (already called during spring context creation)
		if (stopwords != null) {
			for (String stopword : stopwords) {
				if (content.contains(stopword)) {
					throw new IllegalStateException("command [" + command.getCommandName() + "] causes page content with stopword: " + stopword);
				}
			}
		}
		return result;
	}

}

The sample class

package de.demo.proxy;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class MainClass {
	
    @Autowired
	private WebDriver driver;
    
    public void start() {
        driver.get("http://www.google.com");

        // Find the text input element by its name
        WebElement element = driver.findElement(By.name("q"));

        // Enter something to search for
        element.sendKeys("Hello");

        // Now submit the form. WebDriver will find the form for us from the element
        element.submit();

        // Check the title of the page
        System.out.println("Page title is: " + driver.getTitle());
        
        driver.findElement(By.xpath("//a")).click();
        
        driver.close();
    }
	
	public static void main(String[] args) {
			ApplicationContext appCtx = new ClassPathXmlApplicationContext("app.xml");
			MainClass mc = appCtx.getBean(MainClass.class);
			try {
				mc.start();
			} finally {
				mc.driver.close();
			}
	}

}

Posted in Uncategorized | Leave a Comment »