Apology in JavaDoc

Recently I stumbled about a lovely piece of JavaDoc:

/**
  * Because of possible changes of the Jar's name 
  * the actual name has to be determined programmatically.
  *
  * Apology to Baldr, Venus, Aphrodite, Lakshmi, Hathor 
  * and all remaining gods of beauty.
  */
public String getJarName() {
  .... // very ugly code
}

Using Checkstyle’s suppression filters on Windows and Linux

I have already shown the usage of Checkstyle’s suppression filters in Eclipse and Maven in [1]. But after switching from Linux to Windows (please no comments on that…) I wondered about occurring Checkstyle rule violations I actually had excluded in my checkstyle-suppressions.xml. Those rules were mainly simple exclusions of all files within a certain package:

<suppress checks="[a-zA-Z0-9]*" files="src/main/java/de/foo/bar" />

After searching around, I realized that this was an issue with the given regex in the files-attribute [2]. The simple slash was correctly interpreted on Linux, but didn’t work on Windows. So to make the rules work on both operation systems I replaced the path separator with “[/\\]”:

<suppress checks="[a-zA-Z0-9]*" files="src[/\\]main[/\\]java[/\\]de[/\\]foo[/\\]bar" />

Reference

  1. [1] https://rolf-engelhard.de/?p=46
  2. [2] http://checkstyle.2069334.n4.nabble.com/suppression-filter-regex-td2070198.html

Clearing Checkstyle’s Cache in Eclipse

First of all please notice the nice alliteration in the headline.

A little problem which bugged me while searching the solution for [1] was that I had to change my checkstyle.xml and checkstyle-suppression.xml for several times. Unfortunately Eclipse-CS never noticed these modifications. So I restarted Eclipse every time to make the changes apply.

Then I stumbled by chance on an entry in Eclipse-CS’s bug tracker [2]:

“Alternatively to touching the Checkstyle configuration file you can clear the plugin’s caches by clicking the little yellow refresh button on the Checkstyle preferences page.”

And hey—after putting on my glasses and lowering the nose-screen-distance to “way to near”—there it was: a little yellow button on the preference page!

The little yellow checkstyle refresh button.

The little yellow checkstyle refresh button.

Reference

  1. [1] https://rolf-engelhard.de/?p=239
  2. [2] http://sourceforge.net/tracker/?func=detail&aid=1752586&group_id=80344&atid=559497

Selenium 2 / WebDriver—is element present ?

When switching from Selenium 1 to Selenium 2/WebDriver you will notice bitterly that there is no isElementPresent()-method anymore.

Solutions found on the Internet

To fix that issue, one of the most shown solutions on the Internet is the usage of driver#findElement(By) and a try-/catch-statement:

public boolean isElementPresent(String id) {
	boolean present;
	try {
		driver.findElement(By.id(id));
		present = true;
	} catch (NoSuchElementException e) {
		present = false;
	}
	return present;
}

Not very elegant. In addition the JavaDoc of WebElement#findElementy(By) states explicitly, that this method shouldn’t be used “to look for non-present elements”. Instead WebElement#findElements(By) should be used:

public boolean isElementPresent(String id) {
	return driver.findElements(By.id(id)).size() != 0;
}

Although this solution avoids the need of the try/catch-statement, it still lacks in the timeout/implicit waiting functionality Selenium 2 ships with. Every time this method is called, the WebDriver tries to find the element until the given timeout is reached. Therefore our test would wait a certain period of time (to be precise the value set by implicitlyWait) whenever this method is about to return ‘false’.

To get ahead of that, you can explicitly set the timeout:

public boolean isElementPresent(String id, WebDriver driver) {
	boolean present;
	
	driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
	boolean present = driver.findElements( By.id(id) ).size() != 0;
	driver.manage().timeouts().implicitlyWait(1000, TimeUnit.SECONDS);
	
	return present;
}

Problem when using the Page-Object-Pattern

The big dissapointment: when using the Page-Object-Pattern in conjunction with the @FindBy-Annotation you are constrained to implement the WebElement’s id at least twice:

@FindBy(id="fooId")
private WebElement webelement;

public void testSome() {
	...
	isElementPresent("fooId", driver);
	...
}

So if “fooId” changes its value, you have to fix that in your code on multiple positions. That should be avoided.

A (half-way clean) solution

I tried to overcome that problem by passing the WebElement directly to my isElementPresent-Method. As a result, I’m able to hold the id on one single position in my code. As a drawback (or advantage) I’m unable to use the id in my isElementPresent-Method anymore. This is caused by the absence of a suitable way in the WebElement’s API to get the by-value (eg. By.id(“foo”)) which is used to find the element. Therefore using WebDriver#findElements(By) gone out of reach.

Finally I step back to the solution I preliminary declared as “not very elegant”: I use a try-/catch-statement in which I call a method on the webelement which throws an NoSuchElementException in case the element is not present:

public static boolean isElementPresent(WebDriver webdriver, WebElement webelement) {	
	boolean exists = false;

	webdriver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);

	try {
		webelement.getTagName();
		exists = true;
	} catch (NoSuchElementException e) {
		// nothing to do.
	}

	webdriver.manage().timeouts().implicitlyWait(1000, TimeUnit.MILLISECONDS);

	return exists;
}

Note:

  • If I have to deliberate about whether avoiding the try/catch-statement or avoiding to code the ids mulitple times, I actually prefer the last one.
  • If your value for implicitly wait differs from 1000, calling this method will obviously overwrite the current value.

A quick refactoring using TestNG’s expectedExceptions

I recently crossed a TestNG-test which looked like this:

@Test
public void noResultsTest() {
	// test
	String query = " ";
	Exception exception = null;
	List foos = null;
	try {
		foos = barService.search(query);
	} catch (SystemError e) {
		// input was wrong
		exception = e;
	}

	// assert
	Assert.assertNotNull(exception, "There was an exception");
	Assert.assertNull(foos);
}

Obviously this test should check that barService#search throws an Exception in case the input is a blank.

But there are a few things to mention:

  • TestNG is capable of checking if an expected exception was thrown in a test. Simply use @Test(expectedExceptions={..}).
  • The check that Assert.assertNull(foos) holds true is useless. Either no exception was thrown and Assert.assertNotNull(exception, "There was an exception") will fail or an exception was thrown and foos will not be assigned with any value.

So the test could be rewritten like this:

@Test(expectedExceptions={ SystemError.class })
public void keineBerufeTest2() throws SystemError {
	foos = barService.search(" ");
}