Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

If You Use Selenium for Browser-based UI Acceptance Testing, You Might Like Selenide

Internal and external quality metrics

Software has two quality metrics, external and internal quality. External quality is how well the system meets the needs of its customers and users (is it functional, reliable, available, responsive, etc.), and internal quality is how well it meets the needs of its developers and administrators (is it easy to understand, easy to change, etc.).

For measuring external quality, we have to write acceptance tests that test our system end-to-end. An end-to-end test interacts with the system only from the outside: through its user interface, by sending messages as if from third-party systems, by invoking its web services, by parsing reports, and so on. At ZeroTurnaround, we rely on Selenium for acceptance testing, so it was cool to find out a couple of months ago about Selenide (we suspect it’s pronounced as SEL-le-nide, rhymes with tide), which we now use for tests for UI activities in LiveRebel, our “bulletproof release tool”. Selenide is a concise and, as Codeborne engineers call it, expressive wrapper API specifically for Selenium WebDriver, which is used to control browser actions. So I thought I’d share a couple interesting/notable things about Selenide with you here.

Selectors

An integral part of functional/acceptance UI test is selection of an element. You need to select an element to interact with it, check its state, wait for some condition to come true, etc. Selenide makes this as easy and fluent as possible.

Selenide offers following (jQuery-like) ways for selecting element/elements:

  • $(String cssSelector) – returns SelenideElement
  • $(By) – returns SelenideElement
  • $$(String cssSelector) – returns ElementsCollection
  • $$(By) – returns ElementsCollection

There are multiple useful static factory methods in the Selectors class for creating different By selectors.

  • byText – search by text (substring)
  • withText – search by exact text string
  • by – search by attribute
  • byTitle – search by “title” attribute
  • byValue – search by “value” attribute

As elements in the DOM are hierarchical, sometimes you may want to select some element that resides in another element. In this case, Selenide allows you to chain selecters.

For example, you can select some row from a table in the following way:

SelenideElement roundHouseRow = $(“.table”).$(byText(“Norris”));

Conditions

Nowadays, many websites use AJAX to change some parts of the website dynamically, which means we need to wait for some conditions to come true when we test our application. For that purpose, Selenide has a Condition class. Unlike Selenium, Selenide waits for some predefined timeout for the given Condition to come true. By default, the timeout to wait for is 4 seconds, this is of course configurable (via selenide.timeout property). Conditions are also used for testing that webpage has expected elements and that elements have the desired state.

Some out-of-the-box Conditions you can use:

  • visible
  • hidden
  • present
  • notPresent
  • readonly
  • matchText(String text) – for matching substring
  • text(String text) – for matching whole text
  • not(Condition condition) – for negating condition

As Condition class is abstract,  users can easily define new Conditions that one might need.

Here is a little example that checks that a query button is present and visible on the page and clicking on it produces expected result.

SelenideElement queryButton = $(“#query-button”);
queryButton.shouldBe(present, visible);
queryButton.click();
SelenideElement result = $(“#query-result”).waitUntil(present);
result.shouldHave(text(“Chuck”));

From this example, we can also see that Selenide has put an effort into making all the statements as readable as possible, even by non-technical staff. +10 for that!

ElementsCollection

HTML has multiple constructs that consist of multiple elements, like tables with multiple rows, multiple options for a selected element, radio button groups, different kinds of lists and more. We might have multiple elements that have the same name, or we want to perform operations on all elements that have the same class. So we’ll need a construct that allows us to perform operations on multiple elements, and Selenide has handy ways to work with collections of elements: ElementsCollection.

You can perform following actions on collections of elements:

  • shouldBe – e.g. $$(".errors").shouldBe(empty)
  • shouldHave – e.g. $$("#mytable tbody tr").shouldHave(size(2))
  • find – e.g. $$("#multirowTable tr").findBy(text("Norris"))
  • filter – e.g. $$("#multirowTable tr").filterBy(text("Norris"))
  • exclude – e.g. $$("#multirowTable tr").excludeWith(text("Chuck"))

ScreenShooter

From time to time, your tests are going to fail. That’s ok! For cases like this, we would like to have as much information as possible to quickly hunt down the reason of the failure. To help you figure out what happened, Selenide lets you take a snapshot of the browser window upon test failure, and screenshot of the webpage along with the HTML content is stored for your debugging pleasure. It’s also set up to use with JUnit and TestNG. Cool, right?

Using with JUnit runner

@Rule
public final ScreenShooter makeScreenshotOnFailure = ScreenShooter.failedTests();

Using with TestNG runner

Annotate your test class with @Listeners({ ScreenShooter.class})

Custom browser capabilities

Out-of-the-box browsers supported by Selenide have some of the most common capabilities set for corresponding Selenium WebDriver, plus JavaScript and taking screenshots are enabled. If you needs are relatively basic, then you can just start running your tests without any extra configuration. But what if you need to add some more capabilities to the browser? If you use a self-signed certificate for running tests and you need to disable SSL validation on the browser, then you need to further configure the WebDriver. You can do this by implementing the WebDriverProvider interface and passing it as a -Dbrowser parameter  (Deprecated in Selenide 2.4), or passing the driver to WebDriverRunner.setDriver (the currently-recommended way) before starting the test.

Here is an example how to enable Javascript and screenshot taking and how to disable SSL validation for a phantomJS headless browser:

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setJavascriptEnabled(true);
capabilities.setCapability("takesScreenshot", true);
capabilities.setCapability("phantomjs.cli.args", new String[] {"--ignore-ssl-errors=true"});
WebDriver driver = new org.openqa.selenium.phantomjs.PhantomJSDriver(capabilities);
WebDriverRunner.setDriver(driver);

All seems pretty simple, right?

Conclusion

All in all, Selenide is really nice and capable tool for writing functional/acceptance tests for your browser-based UI. Its declarative style makes your tests readable and easily exposes their intent. Good readability of the tests is good quality to have, because your test are supposed to describe and document your application’s behavior. Writing tests using  Selenide is easy as well, to quote authors of Selenide – “Just type: $(selector). – and IDE suggests you all the options.” I encourage you to check Selenide out and give it a try. Leave comments below and let us know how it goes at @ZeroTurnaround.

 

  • Yakiv Kramarenko

    Thanks for the article! I’m glad to see more people started to use Selenide:)

    Just a small note from my side. For me one of the killer-features of Selenide, not mentioned much, is IMHO the most convenient and easy to use ability to implement custom conditions. Because often web application has its own implementation of element states – enabled, checked, active, selected.

    And finally Selenide is not a framework, but a library, what gives you much freedom of writing tests the way you want;)

  • Andrei Solntsev

    Great article, thank you!

    Feel free to share your suggestions for further evolution of Selenide.

    Actually there is no good reason for deprecating WebDriverProvider other that nobody uses it. I guess… And there is simpler alternative.

  • Uhm.. My feeling is that it’s nice for spaghetti tests, written in procedural style, but I’m not sure selenide can fit in a proper oo test suite/framework, using best practices like page objects and e.g. PageFactory

  • Andrei Solntsev

    Hi Alberto!

    It’s up to you if you choose procedural style, spaghetti code or best practices. Selenide does not stop you from using PageFactory, OOP or anything else.

    By the way, Selenide doc describes how to use PageObject pattern. It’s even simpler with Selenide: http://selenide.org/documentation/page-objects.html