Symphonious

Living in a state of accord.

Alert Dialogs Do Not Appear When Using WebDriverBackedSeleniu

With Selenium 1, JavaScript alert and confirmation dialogs were intercepted by the Selenium JavaScript library so they never appeared on-screen and were accessed using selenium.isAlertPresent(), selenium.isConfirmationPresent(), selenium.chooseOkOnNextConfirmation() and similar methods.

With Selenium 2 aka WebDriver, the dialogs do appear on screen and you access them with webDriver.switchTo().alert() which returns an Alert instance for further interactions.

However, when you use WebDriverBackedSelenium to mix Selenium 1 and WebDriver APIs – for example, during migrations from one to the other – the alerts don’t appear on screen and webDriver.switchTo().alert() always throws a NoAlertPresentException. This makes migration problematic because selenium.chooseOkOnNextConfirmation() doesn’t have any effect if the next confirmation is triggered by an action performed directly through Web Driver.

The solution is to avoid WebDriverBackedSelenium entirely and instead create a WebDriverCommandProcessor, configure it to not emulate dialogs and pass it to DefaultSelenium.

public Selenium createSelenium(
  final WebDriver webDriver,
  final String baseUrl)
{
  WebDriverCommandProcessor commandProcessor =
    new WebDriverCommandProcessor(baseUrl, () -> webDriver);
  commandProcessor.setEnableAlertOverrides(false);
  processor.start();
  return new DefaultSelenium(commandProcessor);
}

The key method call here is setEnableAlertOverride(false) which disables the alert emulation.  Note that the Selenium 1 methods for interacting with dialogs will no longer work – you have to switch all alert handling over to WebDriver.

Also note the subtle but important use of a closure to provide a Supplier<WebDriver> instead of just passing the webDriver. The overloaded constructor instance that takes a WebDriver immediately calls start() on the processor and setEnableAlertOverrides must be called before start().

It’s unfortunate, but understandable, that Selenium 1 and WebDriver style alert interactions can’t be mixed as that would make migration a lot easier. At least with this approach you can convert your alert interactions over in one batch then convert all the other interactions incrementally.

Testing@LMAX – Introducing ElementSpecification

Today LMAX Exchange has released ElementSpecification, a very small library we built to make working with selectors in selenium/WebDriver tests easier. It has three main aims:

  • Make it easier to understand selectors by using a very English-like syntax
  • Avoid common pitfalls when writing selectors that lead to either brittle or intermittent tests
  • Strongly discourage writing overly complicated selectors.

Essentially, we use ElementSpecification anywhere that we would have written CSS or XPath selectors by hand. ElementSpecification will automatically select the most appropriate format to use – choosing between a simple ID selector, CSS or XPath.

Making selectors easier to understand doesn’t mean making locators shorter – CSS is already a very terse language. We actually want to use more characters to express our intent so that future developers can read the specification without having to decode CSS. For example, the CSS:

#data-table tr[data-id='78'] .name

becomes:

anElementWithId("data-table")
.thatContainsA("tr").withAttributeValue("data-id", "78")
.thatContainsAnElementWithClass("name")

Much longer, but if you were to read the CSS selector to yourself, it would come out a lot like the ElementSpecification syntax. That allows you to stay focussed on what the test is doing instead of pausing to decode the CSS. It’s also reduces the likelihood of misreading a vital character and misunderstanding the selector.

With ElementSpecification essentially acting as an adapter layer between the test author and the actual CSS, it’s also able to avoid some common intermittency pitfalls. In fact, the reason ElementSpecification was first built was because really smart people kept attempting to locate an element with a classname using:

//*[contains(@class, 'valid')]

which looks ok, but incorrectly also matches an element with the class ‘invalid’. Requiring the class attribute to exactly match ‘valid’ is too brittle because it will fail if an additional class is added to the element. Instead, ElementSpecification would generate:

contains(concat(' ', @class, ' '), ' valid ')

which is decidedly unpleasant to have to write by hand.

The biggest benefit we’ve seen from ElementSpecification though is that fact that it has a deliberately limited set of abilities. You can only descend down the DOM tree, never back up and never across to siblings. That makes selectors far easier to understand and avoids a lot of unintended coupling between the tests and incidental properties of the DOM. Sometimes it means augmenting the DOM to make it more semantic – things like adding a “data-id” attribute to rows as in the example above. It’s surprisingly rare how often we need to do that and surprising how useful those extra semantics wind up being for a whole variety of reasons anyway.

The Single Responsibility Principle (and what’s wrong with it)

Marco Cecconi – I don’t love the single responsibility principle:
The principle is arbitrary in itself. What makes one and only Reason To Change™ always, unequivocally better than two Reasons To Change™? The number one sounds great, but I’m a strong advocate of simple things and sometimes a class with more reasons to change is the simplest thing. I agree that we mustn’t do mega-classes that try to do too many different things, but why should a class have one single Reason To Change™? I flatly disagree with the statement. It’s not supported by any fact. I could say “three” reasons and be just as arbitrary.
Interesting critique of the single responsibility pattern. The quote above is perhaps one of the weaker arguments against the single responsibility pattern but it struck a nerve with me because all too often we assume that because a rule sounds good it has some validity. In reality, picking one responsibility for a class is quite arbitrary and, as the article argues, deciding what a responsibility is is even more arbitrary.
So, whilst I agree completely on the premise of not make ginormous classes, I think this principle is not at all helpful in either illustrating the concept or even identifying unequivocally problematic cases so they can be corrected. In the same way, anemic micro-classes that do little are a very complicated way of organizing a code base.
Given I’ve spent time today fixing a bug that was almost entirely caused by having too many classes with too focused responsibilities which caused the combined structure to be difficult to reason about and have unintended consequences this resonates strongly as well. Making responsibilities too fine grained is just as detrimental to the maintainability of code and somewhat counterintuitively also to it’s reusability. Reusing a single class is far simpler than having to work out how to piece together ten separate classes in the right way (hence the existence of builders which create a facade that everything is really a single unit again). I can see a lot of value in discussing things in terms of coupling and cohesion rather than responsibilities and using those concepts to find the right balance.

Javassist & Java 8 – invalid constant type: 15

Here’s a fun one, we have some code generated using javassist that looks a bit like:

public void doStuff(byte actionId) {
switch (actionId) {
case 0: doOneThing(); break;
case 1: doSomethingElse(); break;
default:
throw new IllegalArgumentException("Unknown action: " + actionId);
}
}

This works perfectly fine on Java 6 and Java 7 but fails on Java 8.  It turns out the problematic part is "Unknown action: " + actionId. When run on Java 8 that throws “java.io.IOException: invalid constant type: 15” in javassist.bytecode.ConstPool.readOne.

The work around is simple, just do the conversion from byte to String explicitly:

throw new IllegalArgumentException("Unknown action: " + 
String.valueOf(actionId));

There may be a more recent version of Javassist which fixes this, I haven’t looked as the work around is so trivial (and we only hit this problem in the error handling code which should never be triggered anyway).

Why Are My JUnit Tests Running So Slow?

This is mostly a note to myself, but often when I setup a new Linux install, I find that JUnit tests run significantly slower than usual. The CPU is nearly entirely idle and there’s almost no IO-wait making it hard to work out what’s going on.

The problem is that JUnit (or something in our tests or test runner) is doing a DNS lookup on the machine’s hostname. That lookup should be really fast, but if you’re connected to a VPN it may search the remote DNS server which takes time and makes the tests take much longer than they should.

The solution is to make sure your hostname is in /etc/hosts pointing to 127.0.0.1 (and that /etc/hosts is searched first but it usually is). Then the lookup is lightning fast and the tests start maxing out the CPU like they should.