Selenide, I think this is the beginning of a beautiful friendship
Tags: selenide, selenium, testautomation, e2etesting
Published: 2022-02-04 19:10:33

---
title: Selenide, I think this is the beginning of a beautiful friendship
published: true
date: 2022-02-03 08:56:15 UTC
tags: selenide, selenium, testautomation, e2etesting
canonical_url: https://mszeles.com/selenide-i-think-this-is-the-beginning-of-a-beautiful-friendship
---
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv08rvoufluyebgp6xiu.jpg)
As I promised we will start coding in this section as soon as possible. In case you missed [my previous article](https://dev.to/mszeles/selenium-or-selenide-a67-temp-slug-2966040), I highly recommend reading it beforehand, as I have provided many reasons why you should give Selenide a try.

## Setup

- You will need the Java Development Kit. I suggest getting the latest [Open JDK 17](https://dev.to/mszeles/selenium-or-selenide-a67-temp-slug-2966040).
- As an IDE I am using [IntelliJ IDEA](https://www.jetbrains.com/idea/download/), but you can use anything you like. Besides IntelliJ, [Eclipse](https://www.eclipse.org/downloads/) and [Visual Studio Code](https://code.visualstudio.com/download) are the most popular ones. 
- For source code management I use **Git** , you can find the project on [GitHub](https://github.com/mszeles/selenide-tutorial).
- I usually use Maven for Java projects, but this is the perfect opportunity to learn something new, so I will use [Gradle](https://gradle.org/install/) this time. In case I make any stupid mistake with Gradle, do not hesitate to tell me 😉
- As Java testing framework TestNG and JUnit are the most popular ones. I will go with **TestNG but** I will provide the required info for JUnit 5 as well. That's all you will need for the project. 

Let's continue with creating a Gradle project and openening the **build.gradle** file. Let's add the dependencies:

```
dependencies {
    testImplementation 'org.testng:testng:7.5'
    implementation 'com.codeborne:selenide:6.2.1'
    implementation 'org.seleniumhq.selenium:selenium-java:4.1.1'
}

```

For JUnit:

```
dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
    implementation 'com.codeborne:selenide:6.2.1'
    implementation 'org.seleniumhq.selenium:selenium-java:4.1.1'
}

```

Specify to use TestNG:

```
test {
    useTestNG()
}

```

for JUnit:

```
test {
    useJUnitPlatform()
}

```

We are ready to go. Only one question remains. **Which site will we test?**

Have you ever enrolled in a highly rated course to learn about test automation just to realize half of the pages which were used as examples in the course are not existing anymore or have been changed completely? Well, it happened to me. My choice is (almost) all developers' second favourite site (right after Google) [Stackoverflow](https://gradle.org/install/). My third favourite is [Baeldung](https://gradle.org/install/) if you are interested 😊. I am pretty sure Stackoverflow won't disappear in the near future, but of course, I cannot guarantee it won't change its design.

It is time to write our first test. Yayyy. Let's start with something simple.

## Open Stackoverflow

Using **Selenide** you do not have to use the WebDriver directly as it is **automatically opening and closing the browser** for us using **Chrome** by default. We can open the page with one single line without any extra configuration.

```
@Test
public void openPage() {
    open("https://stackoverflow.com/");
}

```

Just run the test and you will see Stackoverflow opening and then closing immediately. Whenever I develop and look for DOM elements, **I prefer to open the same page in my browser in incognito mode so I can see exactly the same result I would see whenever I open it via Selenide.** Let's do this now.

![Stackowerflow homepage](https://cdn.hashnode.com/res/hashnode/image/upload/v1643875645433/QJ233Hjc0.png)

The first thing I notice is that we have an accept cookie banner on this page. As in these days, we have something similar on every website, let's accept the cookie. But before that let's finish our first test. **Every worthwhile test should check some conditions.**

## Checking visibility and enabled state of elements

Of course, we could select many conditions to test, but in this case, I will concentrate on **demonstrating** the different ways of **Selenide condition checking**. Let's **verify we have a visible Login and a Sign up button**. In order to do that, first, we have to find the element. Looking at the **DOM in Chrome dev tools** (or of course, you can use Firefox or other tools if you prefer that) we can see that the **Login button is actually a link**. It has no id, but it **has a class** _login-link_ **which seems unique**. So I could use a simple CSS selector or even an id based selector. But is it really unique?

If you watch carefully, you can notice despite its name, the Sign up link has the **same** _login-link_ **class** as the Login button, so I will have to **select based on an index**. For that purpose, I am using XPath (in general **prefer CSS over XPath as it is faster** ).

![Stackoverflow Sign Up link source code](https://cdn.hashnode.com/res/hashnode/image/upload/v1643876258829/u5GF9Ca3-.png)

You might think we should **use the text to find the element** as it is unique, but **I do not recommend** that as according to my experience **texts are changing more often than ids and classes** , not even talking about **testing with different languages.**

Let's write the selector:

```
$x("(//a[contains(@class, 'login-link')])[1]");

```

It is very simple, concise and straightforward. You can use **$(String cssSelector), $$(String cssSelector)** to find an element($) or elements($$) by CSS. Similarly, you can use **$x(String xpath) and $$x(String xpath)** to find elements using XPath. Of course, you can use the built-in Selenium **By** commands also, using **$(By) and $$(By)**. Selenide even provides [new selectors](https://selenide.org/javadoc/current/com/codeborne/selenide/Selectors.html) in addition to the normal Selenium selectors like [byText](https://selenide.org/javadoc/current/com/codeborne/selenide/Selectors.html#byText-java.lang.String-), [withText](https://selenide.org/javadoc/current/com/codeborne/selenide/Selectors.html#withText-java.lang.String-)and [byAttribute](https://selenide.org/javadoc/current/com/codeborne/selenide/Selectors.html#byAttribute-java.lang.String-java.lang.String-).

In case you are not familiar with the basic Selenium selectors, I recommend again [Rahul Shetty's Udemy Course](https://www.udemy.com/course/selenium-real-time-examplesinterview-questions) on Selenium. You will have a good grasp of them after finishing the course. One additional resource which is quite good for beginners is [CSS Dinner](https://www.udemy.com/course/selenium-real-time-examplesinterview-questions).

Now that we have the element which is a SelenideElement (subclass of WebElement) we can verify its visibility:

$x("(//a[contains(@class, 'login-link')])[1]").shouldBe(visible); It is easy to read this code. Actually writing it is also easy and fun. 😀 You could ask what happens **in case the element is not immediately present in the DOM** , or what if it is present but **it needs some time to become visible? Selenide uses implicit waits** both during finding elements and also during evaluating conditions. The **default is 4 sec** , but it can be configured. The should functions ( **should, shouldHave, shouldBe, ShouldNot, shouldNotHave, shouldNotBe** ) even have an overloaded version which also accepts a Duration to specify the timeout explicitly.

You can run your test from your favourite IDE, or you can run it from the command line using Gradle:

```
gradlew test

```

Simply change the "visible" to "enabled" to check the enabled state of an element:

```
$x("(//a[contains(@class, 'login-link')])[1]").shouldBe(enabled);

```

Based on the previous example it is quite easy to write the verification for the Sign Up link:

```
$x("(//a[contains(@class, 'login-link')])[2]").shouldBe(visible);
$x("(//a[contains(@class, 'login-link')])[2]").shouldBe(enabled);

```

## Let's refactor

Before moving on, let's do some **refactoring** , so we can make the code cleaner and we can get one step closer to the Page Object Model about which I will write in a later article. Let's do 2 things. First, **extract** the Login and Sign Up **elements as constants using meaningful names.** In case you are worried about locating an element before the page even exists, then I have some good news for you. Selenium (so also Selenide) use **lazy initialization** which means the elements will only be located, whenever you call some methods on them. Second, we will use **method chaining** to get a more **concise code**. I really like this technique as you will see it in later articles. So here is the code after refactor:

```
public class HomepageTest {

    private final SelenideElement loginLink = $x("(//a[contains(@class, 'login-link')])[1]");
    private final SelenideElement signUpLink = $x("(//a[contains(@class, 'login-link')])[2]");

    @Test
    public void openPage() {
        open("https://stackoverflow.com/");
        loginLink.shouldBe(visible).shouldBe(enabled);
        signUpButton.shouldBe(visible).shouldBe(enabled);
    }
}

```

## Finding elements based on text

As I promised, we will get to the cookie banner soon. Just one more thing before that. As I said it is not the best idea to locate elements based on texts, but **sometimes you simply have no other options** (of course you can find everything with absolute xpath expressions, but that is a horrible idea as it will break on the slightest change of the UI), or **you have to check if elements have a certain text.** This time we will stick to English but later I will write an article about internationalization.

Let's find the link with the text "About" and verify whether it is pointing to the right location.

We can choose from a couple of options here:

## Finding using XPath

```
$x("//a[text()='About']");
$x("//a[contains(text(), 'bout')]");

```

You can check for exact matches or partial matches with XPath.

## Finding using linkText or partialLinkText

```
$(By.linkText("About"));
$(By.partialLinkText("bout"));

```

You can find the element using the standard Selenium locators.

Find using byText and withText $(byText("About")) $(withText("bout"));; You can also find an element using Selenide locators. **byText** is similar to linkText as it finds an element using an exact match for the text, and **withText** is similar to partialLinkText as it checks whether the element's text contains the given text or not. But there is a huge advantage here for Selenide: it **works with every kind of element** , not just with links.

## Verifying link reference

This is quite simple:

```
aboutLink.shouldHave(href("/company"));

```

I highly recommend checking the Conditions class's [documentation](https://selenide.org/javadoc/current/com/codeborne/selenide/Condition.html), so you can get a good grasp on the different conditions offered by Selenide.

## Closing the banner

Finally, we arrived at the last topic of today's article which is accepting the cookies. Let's create another test called _acceptCookies_. First, let's find the accept button:

![Stackoweflow source code part for accept cookie button](https://cdn.hashnode.com/res/hashnode/image/upload/v1643876980344/ElEdtRwE3.png)

Looking at the page source we can see it is a button that we have to click and it has a **class** _js-accept-cookies_ which **can identify the button**. So we can easily find it by class name:

```
$(byClassName("js-accept-cookies"));

```

After finding the button we can **click it by simply using the click()** method on it as we could have already learnt it using Selenium.

```
acceptCookiesButton.click();

```

In case the test does not fail we can tell we were able to click the accept cookie button, but **to be on the safe side let's verify whether the banner has really disappeared**. The banner is a div having a class js-consent-banner. In order to verify it is not there anymore we can use the **shouldNotBe** method:

```
private final SelenideElement acceptCookieBanner = $("div.js-consent-banner");
.
.
acceptCookieBanner.shouldNotBe(visible);

```

or you can write:

```
acceptCookieBanner.shouldBe(hidden);

```

Actually **should, shouldBe and shouldHave are synonyms similarly to their counterparts shouldNot, shouldNotBe, shouldNotHave.** They are interchangeable and also there are many synonyms among the conditions, so basically it is up to you which you find more readable. These examples mean the same:

```
acceptCookieBanner.shouldBe(hidden);
acceptCookieBanner.shouldNotBe(visible);
acceptCookieBanner.should(disappear);
acceptCookieBanner.shouldNot(appear);

```

I prefer not using negation so I am going with **shouldBe(hidden).**

## Finishing touches

Before we finish let's do **2 more refactors to reduce duplication and to make the code even simpler.**

As we are testing the same homepage in these tests, **we can move the page opening to a common part that executes before each test.** In TestNG you can use the @BeforeMethod annotation for this, using JUnit 5 the @BeforeEach will be your solution. To get a good comparison of the usage of the two frameworks, check [this article on Baeldung](https://www.baeldung.com/junit-vs-testng).

When verifying the Login and Sign Up link we used **2 chained shouldBe** methods to verify whether the component is visible and enabled. Actually, **you can merge them into one call** , as the should methods can accept multiple conditions.

This is the final code:

```
public class HomepageTest {
    private final SelenideElement loginLink = $x("(//a[contains(@class, 'login-link')])[1]");
    private final SelenideElement signUpLink = $x("(//a[contains(@class, 'login-link')])[2]");
    private final SelenideElement aboutLink = $(byText("About"));
    private final SelenideElement acceptCookiesButton = $(byClassName("js-accept-cookies"));
    private final SelenideElement acceptCookieBanner = $("div.js-consent-banner");

    @BeforeMethod
    public void setup() {
        open("https://stackoverflow.com/");
    }

    @Test
    public void openPage() {
        loginLink.shouldBe(visible, enabled);
        signUpLink.shouldBe(visible, enabled);
        aboutLink.shouldHave(href("/company"));
    }

    @Test
    public void acceptCookies() {
        acceptCookiesButton.click();
        acceptCookieBanner.shouldBe(hidden);
    }
}

```

It looks neat, don't you think? 😊

And that's all. We have finished today's lesson. I hope you enjoyed it. **Don't hesitate to share your thoughts about this article and suggest topics for upcoming ones.** In the next post, **I will develop tests for Stackoverflow's Questions page.**

📚 Before we finish, I **give you an assignment**. I used XPath to find the Sign up link. **Write a CSS selector (not using the text of the link) to find the Sign up link!** Please do not post your solution immediately, give some times to the others. So I ask you to **post your solution on Monday** ❣️

[Buy me a coffee!](https://buymeacoffee.com/mikiszeles) ❤

See you soon...

Github: [https://github.com/mszeles/selenide-tutorial](https://github.com/mszeles/selenide-tutorial)

📚**Join the Selenide community** on [LinkedIn](https://www.linkedin.com/groups/9154550/)! ✌

P.S.: **Support me by sharing this article if you like it.** 👍