Loading...

Selenide vs Fluentlenium #1 - Creating simple scenario

 Selenium WebDriver is the most popular tool used for test automation of web applications. There are also a lot of frameworks which is based on Selenium but adds to it some useful functionality or solves some problems. This article is the first part of the series in which I compare two amazing Selenium based frameworks dedicated for Java language: Fluentlenium and Selenide. So if you are before making decision if the framework you will create should be based on Selenium WebDriver or any of its wrapper then this article is perfect for you. In this article we will focus on creating simple scenario in those two frameworks and describing the differences on that level.

Let's start from creating the simple test in Selenide. Assume that I just want to make the framework working and I am not focusing on the framework architecture. If I just want to start, Selenide looks really great because to make it working we just need to add Selenide requirement to maven and that is all.

<dependency>
	<groupId>com.codeborne</groupId>
	<artifactId>selenide</artifactId>
	<version>${selenide.version}</version>
	<scope>test</scope>
</dependency>


We do not need to worry about drivers for all browsers we want to support and adding them to system variables. The only thing we need to worry about is the browsers which have to be installed. This works great at least with Firefox and Chrome (with IE you still need perform some configuration). The one disadvantage I can think about is the static configuration so I guess that we can't e.g. run tests in parallel in different browsers.


When our maven dependencies are ready we can write our first test which looks like this:

package com.testcraftsmanship.selenide;

import com.codeborne.selenide.Configuration;
import org.junit.Test;

import static com.codeborne.selenide.Condition.text;
import static com.codeborne.selenide.Selenide.$;
import static com.codeborne.selenide.Selenide.open;

public class QuickStartTest {

    @BeforeClass
    public static void setUp() {
        Configuration.browser = "chrome";
    }

    @Test
    public void itShouldBePossibleToSearchThePhrase() {
        open("https://duckduckgo.com");
        $("#search_form_input_homepage").setValue("Selenium");
        $("#search_button_homepage").click();
        $(".module__title__link").shouldHave(text("Selenium"));
    }

}


What the test do is just navigating to https://duckduckgo.com, searching the Selenium phrase and verifying that this phrase is displayed in the title of the search results. If we are talking about the code then the setUp() method is not required in the example but I added it just to show you how can we define which browser we want to perform tests on - here we select Google Chrome. In the test I have used open("https://duckduckgo.com") method which simply open browser and navigates to the https://duckduckgo.com web page. Method $("#search_form_input_homepage") returns the Selenide wrapper of Web Element which is search by css selector passed as an argument. The element allows us to perform many actions like setValue which enter the text in the field, click() perform the click action. It is important to add that all those actions contains the wait mechanism under the hood. It means that in most cases you don't need to bother about timing issues (e.g. StaleElementException). Of course in real world waits still have to be written.


If we want to achive the same simple case in Fluentlenium we have to add a few more dependencies to maven:

<dependency>
	<groupId>org.fluentlenium</groupId>
	<artifactId>fluentlenium-junit</artifactId>
	<version>${fluentlenium.version}</version>
</dependency>
<dependency>
	<groupId>org.fluentlenium</groupId>
	<artifactId>fluentlenium-assertj</artifactId>
	<version>${fluentlenium.version}</version>
</dependency>
<dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-chrome-driver</artifactId>
	<version>${selenium.version}</version>
	<scope>test</scope>
</dependency>


Now we need to add separate dependency for test framework (e.g. for junit we have to add fluentlenium-junit), if we want to have more advanced assertions then separate library for assertions (e.g. fluentlenium-assertj as an extension for assertj) and we also have to add selenium drivers dependencies for all browsers we have to test on. Unfortunately we also have to download driver executable for all those browsers and add them to system variables. It looks little bit more complicated but you have to do it only once. Because you do it by your I think that you have a better control over all staff which happens under the hood. The same test scenario in Fluentlenium looks like listed below:

package com.testcraftsmanship.fluentlenium;


import org.fluentlenium.adapter.junit.FluentTest;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.fluentlenium.assertj.FluentLeniumAssertions.assertThat;

public class QuickStartTest extends FluentTest {
    @BeforeClass
    public static void requiredSetUp() {
        String chromeDriverPath = QuickStartTest.class.getResource("/chromedriver.exe").getPath();
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
    }

    @Test
    public void itShouldBePossibleToSearchThePhrase() {
        goTo("https://duckduckgo.com");
        $("#search_form_input_homepage").fill().with("Selenium");
        $("#search_button_homepage").submit();
        assertThat($(".module__title__link")).hasText("Selenium");
    }
}


As we can see the test class is a little bit more complicated because we have to extends FluentTest (different class has to be extended when we use TestNg as a test runner). In the requiredSetUp() method I have added the part we have to somehow add. We have to download and keep somewhere drivers for the browsers we want to test on and set location to those browsers in desired system property (this part work the same as with plane Selenium WebDriver). The syntax of methods used in the test looks very similar to those from Selenide. Instead of open() method here goTo() method is used. The method $("#search_form_input_homepage") also returns Fluendlenium wrapper of Selenium Web Element. On the object we can perform a lot of dedicated methods which extends functionality of Selenium Web Element. The main difference for now is that in Fluentlenium we have a separate class with assertions which is some kind of wrapper of chosen assertion library - in the example above it is wrapper extension of assertj so it has the same syntax. It applies to me more than the solution from Selenide in which assertions can be perform directly from the object you want to verify (of course it is matter of taste). Unfortunately in Fluentlenium waits are not handled automatically which for most of people will be a big disadvantage. In my personal opinion I prefer to control the way of waiting for action to be performed - to avoid bugs covered by an unknown mechanism of waiting for an action to be taken. Here I can see the risk that e.g. is it possible to miss the bug in which to perform an action I have to click the button twice instead of once.

I am finishing the first part of comparison. You can expect a few more articles connected to that topic in the future. I think that if we talk about those two frameworks timing issues and page objects topics requires separate articles.