Test Automation Framework (Selenium with Java) — Alchemy or Translating JIRA with Selenide (with Exercises)

S01E07 of the Test Automation Framework series about everything you’ll need to set up the nice, simple, yet sophisticated framework.

Covered with clear explanations and pretty illustrations.

Sounds like fun? Cool. Now, please, fasten your seatbelts because you’re here for a ride.

S01E01 — What To Automate?

S01E02 — Test Automation Environment and Tools

S01E03 — The First Selenium Test Case

S01E04 — Selenium Foundations Revisited

S01E05 — Page Factory and Elements Related Exceptions

S01E06 — Page Loading Strategies and Waits

S01E08 — JIRA, Selenide, Complex SQL, Java Objects with Equals & HashCode (with Exercises)

S01E09 — Code Review and Refactoring (Part 1)

S01E10 — Code Review and Refactoring (Part 2)

S01E11 — Allure in Action

As you probably noticed so far — Selenium is quite a complex solution. It provides you with everything that is required to successfully automate your browser, hence automating your UI-based Test Cases and even more.

On the other hand — it doesn’t make things easy in terms of the Test Automation Framework’s complexity. That’s why there are a handful of frameworks & libraries that are written with a specific purpose that can enrich and make your Selenium-based Test Automation environment more intuitive and easier to maintain — Selenide, Cucumber, Serenity, Appium to name a few.

In this episode of the Test Automation Framework, we’ll focus on the Selenide which is a Selenium wrapper.

Before we start, I would like you to get familiar with the term Convention over Configuration, which is essentially a software development paradigm that makes our lives better with much less boilerplate code required. Its main flaw is that you have to understand the convention(s) to work efficiently with a particular framework.

If you still don’t get the idea — go back by one episode (S01E05 — Page Factory and Elements Related Exceptions) and imagine how much smoother it would be to work with it, if those issues were taken care of of of by default.

That’s what the Selenide does for us.

Maven is another great example of the Convention over Configuration paradigm, so if you need more detailed information — we’ve covered it in S01E03 — The First Selenium Test Case.

First of all, let’s update the pom.xml file. According to the QuickStart guide from the Selenide webpage, we only need to add one dependency shown below.

We can also remove dependencies that we no longer need — please remove selenium-java, webdrivermanager, and commons-lang3.

Now you can safely remove every class that we’ve created previously, so your project’s structure should look like the one in the picture.

Source code with Starting Point for Selenide based framework is available here: https://github.com/n4bik/test-automation-framework/tree/Alchemy-StartingPoint

In the real-world scenario, there would (most probably) be a separate testing environment setup on a separate machine, that you could launch from a Jenkins or any other automation server, so you can proceed with your tests without interference from other testers or developers. That’s an ideal situation, to be honest, because it requires quite an infrastructure dedicated to the testing.

We’re going to use our local machine to mimic that situation. At this point, we won’t be creating any Jenkins pipelines or anything, 'cause it’s not yet the time for that.

Without further ado — launch the Ultimate Stack Developer application locally and make sure that it’s working by verifying that you can access http://localhost:4200 on your machine.

In case you forgot or haven’t read previous articles — here’s an instruction on how to launch the app within the Docker container: S01E02 — Test Automation Environment and Tools

To make this experience a little more like a real-world, I’ve created a new JIRA board, with Test Cases to automate. It’s available here with credentials as follows

  • login: lgafrvynkhicgvjmri@kvhrr.com
  • password: testautomationframework1337

USD-1 Test Case Implementation

This one is a kinda straightforward type of issue. Go to page, click something and expect something to happen. Easy peasy.

I’ve created a new package called tests.client inside the pl.tomaszbuga so that I have a clear separation of what’s what — it’s just my preference, there is no golden rule or anything. Within that package let’s create a HomePageTests.java file, where we’ll put every test related to the HomePage.

Here’s my solution, using the Selenide on how to approach this ticket.

I’ve dug a little bit into Log4j documentation and apparently, you have to insert Logger in every class instead of extending it from BaseTest if you want to see from what class the logs come from. Also, I made some tweaks, so it’s more colorful and easy to read. Below you can find the line of code to change (from within the resources/log4j2.xml file), to make the logs look like mine:

Colorful logs. [main] is the thread; [ INFO ] is log level; 11:38:09.989 is DateTime; pl.tomaszbuga.tests.client.HomePageTests is a class; Click yellow button is the log message

We’re logging the “Open Homepage” message and we’re using Selenide’s open() static method to use the proper WebDriver and its .get() method to open “http://localhost:4200”. You don’t have to worry anymore about configuring the WebDriver by yourself, because Selenide got you covered!

We’re logging the “Click yellow button” message and we’re using Selenide’s $() method to use the proper find the element by the cssSelector (if we want to use XPATH the method is $x()) and we’re executing .click() on the found element.

Have you noticed how there are no waits anywhere? This is because Selenide has implemented waits out-of-the-box and we don’t need to worry about that.

At last we’re searching for the “.subtitle-content” and we use the .shouldHave(exactText()) assertion to determine if the Categories page is loaded. In case if the “Please select category” won’t be present on the page the proper message will be logged and the screenshot automatically will be saved. And this is all default Selenide’s settings.

I changed the exactText() value to force the error logs. The screenshot mentioned in the logs is attached below.
As you can see the subtitle clearly states “Please select category” instead of “Please select categor”.

The first ticket is done!

USD-3 Test Case Implementation

This one is even more concise — it’s just getting a page by a User that is not logged in. Let’s get right into it.

We log our action with the “Open Categories page” message.

We’re using the .open() method again to get the address mentioned in the ticket (http://localhost:4200/categories)

In the end, we have to somehow verify that the User is not on the Categories page and to do that I’m using the WebDriverRunner.url() method which is a Selenide method to get access to the WebDriver and get the current URL. With a combination of TestNG’s Assert.assertEquals() and WebDriverRunner.url() we can assert that after opening the Categories page without login — we’re redirected to the root URL (http://localhost:4200/).

The second ticket is done!

I will leave two other tickets related to the HomePage as an exercise for you to try out your skills and knowledge. USD-4 and USD-5 are all yours.

USD-4 Test Case

USD-5 Test Case

USD-6 Test Case Implementation

Checking if the data is being displayed correctly is probably one of the most common tasks to deal with when you’re automating Test Cases. There are plenty of different approaches on how to tackle that and I’m going to show you how to deal with one of the nastiest requirements — compare the data from the WebPage with data from the Database.

To do so — we would need to connect to the Database from within our framework. If you’re well versed with the Java backend development it’s probably a very trivial task for you, but most of the Test Automation adepts are not familiar with such procedures.

In the Java ecosystem, we’re using the Java Database Connector (JDBC) to achieve that. In our particular case, the Database is PostgreSQL, so first of all let’s add proper dependency to the pom.xml file.

That’s step one. The second step would be implementing an actual connection to the Database so that we can perform a query, a SQL query to be precise. Let’s do it.

Create a new package and call it utils

Within pl.tomaszbuga.utils create a new Java class and name it DbConnector. We’re going to use it to connect to the Database and receive a Connection object, that we can use to send queries. Copy the code from below into the DbConnector file. The code is based on the PostgreSQL JDBC documentation.

What code above does? It uses DriverManager.getConnection() method and passes the URL (which in this case is our Database address) and credentials (username and password). After that, it returns a Connection object or SQLException that we would need to take care of. That’s it.

Let’s use the DbConnector to get data from the Database, shall we? Create a new DbDataProvider.java file inside the pl.tomaszbuga.utils and fill it with the code from below.

Plenty is going on, so let’s break that code into pieces.

We’re preparing a new List of a String type to persist the category titles.

We’re using the static method getConnection() from DbConnector class to get the Connection object (which means an actual connection to the Database)

We’re preparing an empty Statement object that we’re going to use to execute and receive an answer from the Database.

We’re executing the “SELECT title FROM category” query and saving it as a ResultSet, which is a special object to persist query results. For visual learners — here’s a picture of the same query executed within the DataGrip app.

Result of the SELECT title FROM category query within DataGrip app
while (resultSet.next()) {
String categoryTitle = resultSet.getString(1);
titleList.add(categoryTitle);
}

This is how we can iterate through ResultSet — while the ResultSet has the next value available — we can perform anything we’d like on that value. The resultSet.getString() method works with both columnIndex (int) and columnLabel (String). In our example, we’re using the columnIndex as we want to receive the first (and only) column value and add it to the titleList.

The last thing I would like to pinpoint is that we’re using a neat feature introduced in Java 7 — the try-with-resources. Here’s a short excerpt from Javadocs:

A resource is an object that must be closed after the program is finished with it.

If not for try-with-resources, we would need to add three methods listed below after each executed query and that would be plenty of boilerplate code.

In case you’re wondering why is it required, here’s a great StackOverflow thread.

Okay, now we have the DbDataProvider.getCategoryTitles() method that we can use to receive a list of categories and compare it with the Category page.

At last, we can create a Test Case automation.

For the sake of not reinventing the wheel, we’re going to use Apache Commons Collections 4 for comparing lists in the assertion. Update the pom.xml file accordingly.

Let’s create a CategoriesPageTests.java file in the pl.tomaszbuga.tests.client package. Copy and paste the code that can be found below.

We’re creating a new Logger for the CategoriesPageTests.

This is just the code from the verifyThatYellowButtonRedirectsToCategoriesPage test from HomePageTests.java that we’re using again to get to the Categories page.

We’re using the $$() method to get a Collection of SelenideElements based on the cssSelector (if you’d like to get a Collection based on the XPATH you should use the $$x() method). After that, we’re using the .shouldBe(sizeGreaterThan(0)) method to wait until Categories are loaded. At last, we’re using the .texts() method to get a list of Category titles as a List of Strings.

Finally we’re using TestNG Assert.assertTrue() method with CollectionUtils.isEqualCollection() (from Apache Commons Collections 4) to compare two List<String> without necessity to sorting elements within Collections.

Another ticket is done!

I will leave another ticket related to the CategoriesPage as an exercise for you to try out your skills and knowledge. USD-7 is all yours.

USD-7 Test Case

In the next episode, we’re going to cover ArticlesPage and ArticleDetailsPage and I’ll show you an even nastier example of Database data validation.

What we’ve learned in this episode?

  • About Convention over Configuration paradigm
  • How to update the pom.xml file to use the Selenide
  • How to translate JIRA ticket into an automated Test Case
  • How to enhance Log4j with %highlight and %style
  • How useful Selenide can be with out-of-the-box settings
  • About the JDBC and how to implement it
  • About the try-with-resources and why to use it
  • How to use the Apache Commons Collections

In case of any questions (I believe there can be one or two of those) — feel free to post them in the comments section below.

All the best,

Tomasz Buga, SDET

www.tomaszbuga.pl

Sources:

GitHub Repository available at: https://github.com/n4bik/test-automation-framework/tree/Alchemy-ClientTests

All illustrations made by Tomasz Buga

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tomasz Buga

Tomasz Buga

Software Development Engineer in Tests. Passionate about programming. Experienced, former employee of the insurance industry. Graphic designer by choice.