Released Selenide 5.4.1

Released Selenide 5.4.1

Statics have won
16.10.19

Good evening!

There is nothing in the World more boring than October. Let’s brighten it up with bright news!

Today we released Selenide 5.4.0 with a couple of noticeable changes which many of you have been asking for a while.

UPD There was a bug in 5.4.0, so please upgrade to 5.4.1

UPD 2 There is also a minor bug in 5.4.1: Configuration.holdBrowserOpen doesn’t work. Will fix it in next version. I hope you don’t use it often.


1. Fixed “IllegalStateException WebDriver has been closed”

Starting from Selenide 5.0.0 (~1 year ago), many users started complaining about
IIlegalStateException WebDriver has been closed....

Actually it’s not a bug, it was intended behaviour. I didn’t want to fix it for a while because I believe such an exception cannot happen in well-designed tests. Selenide threw in intentionally to stimulate people design their tests better.

But we had too many complaints, so I decided to remove this exception - with a heavy heart!

In the end, everyone has the right to fill their own bumps.

How this error happened?

Shortly speaking, this exception happens when instance of SelenideElement is reused with multiple instances of SelenideDriver. It can happen when SelenideElement is declared as a static field (either of a page object or a test). And is initialized before the browser is opened. Or browser is restarted between tests. It also may happen when people use Cucumber which tries to initialize step objects, page objects before opening a browser. Some folks also put Guice or Spring to their test.

All of this is over-engineering. It’s just not needed.

People, you don’t need all these things in tests. Tests must be simple. KISS, amen!

Watch this presentation to know why Static fields are evil.

What’s changed?

But well, people can have different opinions. As a sign of tolerance, let’s meet Selenide 5.4.0

Now this code will work without exceptions:

public class SomeClass {
  private static SelenideElement body = $("body");

  public static void main(String[] args) {
    open("https://mail.ru");
    body.should(exist);

    Selenide.close();

    open("https://mail.ru");
    body.should(exist);   // it threw "IllegalStateException WebDriver has been closed" before Selenide 5.4.0
  }
}

You can find more examples and complaints in issues 862, 902, 954, 922, 873.

If you are interested in implementation details, welcome to PR 989.


2. Now method SelenideDriver.close() always closes the browser

Starting from Selenide 5.0.0, people started complaining that method close() doesn’t close the browser. It happened in (rare) cases when browser was opened by user code, not Selenide.

SelenideDriver browser=new SelenideDriver(new FirefoxDriver());
browser.close(); // it didn't close the browser
browser.getWebDriver().close(); // it did close the browser

Actually it’s not a bug, it was intended behaviour. Selenide initially has this principle: it closed only the browser opened by Selenide itself. And never closed the browser opened by user: it might be used somewhere else.

But again, we had a lot of complaints. It caused a hassle: you see method close(), you call it, it works without exceptions - but the browser is still open.

Now we fixed it. Method close() always closes the browser.

P.S. If your browser is now being unexpectedly closed - feel free to fire a github issue, we will investigate it.

See issue 896 and PR 989


3. We restored short human-readable error messages

You might notice that Selenide 5.3.1 introduced one minor issue. Error messages became longer and hard to read:

com.codeborne.selenide.ex.ElementNotFound: Element not found {#customerDashboardButton}

Now we returned the old good human-readable messages:

Element not found {#customerDashboardButton}

P.S. Poor users of maven-surefire-plugin 2.22.2 will still have long messages, see details here.

See PR 993


4. Added method using for easier switching between multiple webdrivers

As I already said before, using of multiple webdrivers in one test is a bad practice in absolutely most cases.

But again, everyone has the right to fill their own bumps. Now it’s a little more easier to fill that bumps with multiple webdrivers.

Before Selenide 5.4.0, you had to call setWebDriver() all the time - and keep in mind which browser is active at the moment:

var browser1 = new FirefoxDriver();
var browser2 = new FirefoxDriver();

setWebDriver(browser1);
open("http://google.com");
$("h1").shouldHave(text("Released Selenide 5.4.0"));

setWebDriver(browser2);
open("http://yandex.ru");
$("h1").shouldHave(text("Released Selenide 5.4.0"));

now you can wrap code blocks for different browsers in separate using calls:

var browser1 = new FirefoxDriver();
var browser2 = new FirefoxDriver();

using(browser1, () -> {
  open("http://google.com");
  $("h1").shouldHave(text("Released Selenide 5.4.0"));
});

using(browser2, () -> {
  open("http://yandex.ru");
  $("h1").shouldHave(text("Released Selenide 5.4.0"));
});

See PR 976 and code samples in CustomWebdriverTest.java.


5. Added protection against one typical error with xpath

Here is the typical error:

$(".parent").find(By.xpath("/child")).shouldBe(visible);

The problem is that XPath starting with a slash (“/”) looks for element from the root of the document (not from .parent element).

We added a protection. Now this code will throw an exception which clearly states the problem and saves your time:

IllegalArgumentException: XPath starting from / searches from root

The code above can be fixed in different ways (depending on what you actually need):

$(".parent").find(By.xpath("./child")).shouldBe(visible);
$(".parent").find(By.xpath(".//child")).shouldBe(visible);
$(".parent").find(By.xpath("child")).shouldBe(visible);

See PR 963 and PR 975.


6. Upgraded dependencies

  • upgrade to webdrivermanager:3.7.1
  • exclude old Guava dependency coming from net.lightbody.bmp:browsermob-core:2.1.5

Just in case, we discovered a bug in WDM: when you want to download chromedriver 77, it may download “75.0.3770.90” instead. It’s because this version contains substring “77”. Isn’t it funny? :)


News


Andrei Solntsev

selenide.org

16.10.19