Recently I have been exposed to classes in WebDriver that I did not know existed. I started with Selenium when it was beta and found myself inventing methods to do things for Selenium and later for WebDriver. So I never really looked at the extra capabilities for WebDriver. Even before Selenium I often needed to write code that slept for a few seconds. The proper way to use the Thread.sleep method would be:
public void sleep(long ms) { try { Thread.sleep(ms); } catch(InterruptedException ie) { throw new RuntimeException(ie); } }Today I decided to scan through the WebDriver APIs. While I was doing this I found the Sleeper class. It has two APIs which are nice to use. Rather than using the method above you can use:
sleepTight(2000); // sleep for 2000 milliseconds sleepTightInSeconds(2); // sleep for 2 secondsSystemClock
Another helpful class I found was the SystemClock class. It implements the Clock interface and has three functions:
SystemClock sc = new SystemClock(); long current = sc.now(); long early = sc.laterBy(-60000); long later = sc.laterBy(60000) System.out.println(sc.isNowBefore(later)); // true System.out.println(sc.isNowBefore(early)); // false System.out.println(sc.isNowBefore(now)); // falseThe value of 'current' will be the timestamp of now. It is similar to using System.currentTimeMillis() and the API docs actually refer to System.currentTimeMillis(). Obviously, the command immediately after sc.now() will be greater than 'current' just because the call to sc.now() will take some time. The class also has the laterBy method. It talks about passing it a positive long but you can actually pass a negative number. In this case I passed in -60000. The value is in milliseconds. So this would be -60 seconds from 'now'. The third line sets later to 60 seconds later. A few milliseconds will have passed so if the time was 1377825553203 when I called sc.now() then sc.isNowBefore() get called and set 'now' to a few milliseconds later. Maybe 'now' will be 1377825554713. So sc.isNowBefore(later) will be true because later will be around 1377825553203 + 60000 and therefore later than 'now'. Where as sc.isNowBefore(early) will be false because 'now' will be after 1377825553203 - 60000. The odd one is sc.isNowBefore(current). This is because 'current' was now when it was set but a few lines later and 'now' will be after 'current', i.e. now > current, and sc.isNowBefore(current) will be false.
ThreadGuard
This class is more for people writing multi-threaded tests. It is rare for me to write multi-threaded tests. Hopefully you will never have to go there but if you do it is important to know that the implementations of WebDriver (ChromeDriver, FirefoxDriver, InternetExplorerDriver, etc.) are not guaranteed to be thread safe. To make them thread safe you can use the ThreadGuard class. It is actually pretty simple to use. If you have:
WebDriver driver = new FirefoxDriver();You can make it thread safe by changing it to:
WebDriver driver - ThreadGuard.protect(new FirefoxDriver());It is that simple. I won't get into why you are using multi-threaded tests. If you don't know if you are using multi-threading then you are probably not using multi-threading.
UrlChecker
UrlChecker is also a helpful class. It checks to see if a URL is returning an HTTP response of 200 OK. You could use it to check for a URL existing before you navigate to it or do a if URL does not exist then go to a different URL. For example,
try { UrlChecker uc = new UrlChecker(); String testURL = "http://localhost:8080/testapp/index.html"; uc.waitUntilAvailable(5, TimeUnit.SECONDS, new URL(testURL)); driver.get(testURL) } catch(UrlChecker.TimeoutException te) { // if the testURL does not become available in 5 seconds // this code will be run } catch(MalformedURLException mue) { // needed by URL class // if you think the testURL might be malformed handle it here }
Urls
This class has two helpful static methods:
String testURL = "http://localhost:8080/~darrell/tests/#/"; System.out.println(Urls.toProtocolHostAndPort(testURL)); System.out.println(Urls.urlEncode(testURL));The first println will print "http://localhost:8080". As URLs go, the /~darrell/tests/#/ is the context root. If you try going to "http://localhost:8080" it must have a context root. It will just assume you meant "/" for the context root. The second println will print "http%3A%2F%2Flocalhost%3A8080%2F%7Edarrell%2Ftests%2F%23%2F". All the symbols are converted to their ASCII hexidecimal value prefixed with a percent symbol. So for example, %3A is a :, %2F is a /, %7E is a ~ and %23 is the #. There are other interesting classes in WebDriver but these are the less used/discussed classes. Other classes like WindowsUtils have enough happening that they really need their own article. I will say that the following are some interesting classes which require more investigation:
- FluentWait
- Platform
- ProcessUtils
- Select
- Wait
- WindowsUtils