Golden Selenide. My Testing Best Practices

golden selenide. My best testing practices

Attention, the author does not share the concepts of a pure automator or a manual worker, he is an Engineer, a testing engineer who is responsible for both, being a true QA. But the emphasis in the article will go on automation practices

Testing for me is like a whole science with many directions.

What is a test?

The test is a script test, expected === actual result.

What tests are there?

  • Unit (unit) tests (developers write them)

  • UI tests (I write them, and we will stop there)

Briefly about the testing pyramid

Most of all, there should be unit tests, they run much faster than UI tests, helping developers to find bugs in the code faster. Work on the principle 1 test tests one thing.

How do I separate UI test types

  • User scenarios (steps in the system leading to a specific result)

  • Combinations of settings (it is appropriate to apply – test design techniques)

Tester, programmer or analyst, the question is, who lives in the house? – I’ll tell the tester – any automator will have to live there, and then we will talk about locators …

DOM – document object model. Tree-like hierarchy of tags, location of web elements on the page

Distribution of locators

Locator – address/path of the web element on the page

  • store in a separate file, and call it Locators

  • for each page a separate file with locators – forget about it. You will get tired of separating locators across pages, web elements consist of identical forms, css classes, and one locator will often be repeated on different pages of the application. Do you think the file will explode? No, fortunately in the modern world there are powerful IDEs that simplify the search. About 500 locators cover many needs for our project

Intuitive locators

Identifiers are best for declaring locators. Or write intuitive locators. Feel the difference if you write:

.top-header  # Какой то класс
div.top-header  # Блок, но таких блоков может быть много
input.top-header  # Ага, поле ввода
div.top-header.logo  # Ага, сразу понятно, логотип на вверхем хэдере

A long locator is not a problem when they are placed in a separate file with locators:

// WebElementLocators.java

public class ElementLocators {
  
  public static final String HEADER = "div.top-header-block";
  public static final String RED_COLOR = "rgba(248, 248, 248, 1)";
  ...
}

You don’t like me. Which PL to choose for auto tests?

There are three most popular programming languages ​​that make life easier for automators with their frameworks and wide community,

  • Python (Selenium, Unittest/Pytest),

  • Java (Selenide, testNG/JUnit),

  • C# (here I don’t know what is needed for .NET-schikov)

Yes, you can still write in pure JS. Although I consider this the last century, it is especially necessary to understand it. At the QA conference from Kolesa Group, I found out that PHP is used there 😀

Outcome: choose the language in which the developers write. There will be someone to ask in an impasse. (Perhaps the language you are currently writing in has skeletons in the closet)

Patterns? no, haven’t heard

But another problem arises, a heap of text, code, wrapped steps (extra system-specific actions), locators in the test cases themselves. Solution: POM, POM, POM… Page Object Model – standard test automation pattern. The pattern is a set of practices that have stood the test of time and have gone through many crutches. You can’t just take and understand POM. Write your first, second, third hundreds of tests (I implemented after four hundred), and you will understand that something is wrong in them, having come to the moment to study the POM.

PS first you need to step on the rake before you pick it up

What is a script check?

Each test case in my auto tests consists of:

TEST ID (идентификатор теста)
Name (название)
Description (описание)
Steps to reproduce (шаги воспроизведения)
Expected result (ожидаемый результат)
Actual result (фактический результат)

Let’s analyze the composition of the test case in more detail:

  • Expected Result – version of the correct work, how and what should be

  • Actual result – what happened, at what point it broke, what happened

  • Playback steps – the most necessary part of the test case, leading to the final test case. The skill of the tester in the clarity and clarity (briefness) of these steps. Do not neglect this point. Without this, a test case is not a test case.

  • Description – a word for itself, here you can fit a compressed composition of playback steps

  • Name – the name of the autotest function, simplifies the search. I recommend using or ending the title with a verb. SomethingShouldExist. SomethingOfTestingCase.

  • TEST ID – use to count the number of written tests

Life hack. When a test fails, I just copy the test case and paste it into the ticket. It’s good when developers have a repo with tests deployed, where they can run the test themselves. It smells like TDD – (selenide) test driven development. In this case, you write the test until the moment of the UI error, and pass it on to the developers. I think it’s convenient. After the fix, add the autotest and close the case.

TDD is when tests are written before something (function, module, class, object) is implemented. Thus, it helps to collect thoughts and concentrate on tasks, understanding what the code should do and what result the code should give.

What is a web element?

These are all blocks, dots, buttons, divs that make up a web page. Open devtools (F12 for Chrome browser) Anything that has a visual functional block. All these are WEB ELEMENTs. I do not encourage other names.

Explicit waits VS Implicit waits

  • Explicit waits – we wait hardcode, the program sleeps and does nothing. This is the one sleep(1_000); // msec

  • Implicit waits – waits for a given amount of time, each time pinging the element. It will immediately go further if the condition is positive. This way we save test run time. Each should contains an implicit wait

$(HEADER).shouldBe(exist, enabled, visible); 
/*
Состояния:
enabled - активный, в основном применяю для проверки кликабельных элементов
visible - элемент виден на странице
exist - элемент сущетсвует в DOM-е
*/

Complex Conditions

Selenide is very convenient for writing one-liners that clutter up the test code on bare selenium. Under the hood, a regular while loop is used. Selenide waits 4 seconds, each time pinging the element. The timeout config can be set via Configuration.timeout=10_000;. This is the implicit wait.

$(HEADER).shouldBe(exist, enabled, visible)
  .shouldHave(attribute("title", "myTitle"), text("TEXT"));

Difference between should, shouldBe, shouldHave – absolutely none. Use for visually pleasing (readability)

A palette for every taste. Check by color – check webElements color

Selenide is concise, concise and convenient, checking for the presence of an attribute or css of a class? – no problem

$$(DANGER_BTN).shouldHave(size(1)).first()
  .shouldBe(visible)
  .shouldHave(cssValue("background-color", RED_COLOR), cssClass("danger-btn"));

Fight against flock tests

Must have solutions to minimize flaky tests. These solutions will help to minimize their number, but not completely get rid of them.

  1. Restart test. The best option for deadlines and tight deadlines.

  2. Erase and rewrite the test. The probability of writing test replay steps in a slightly different way is high. Therefore, the test can become more stable. Also think about extra steps.

  3. Test retrier – test repeater. Must have thing. Be sure to learn. RetryAnalyzer (reference). A very useful thing, it plays N times until the test turns green or remains red. Cons: a really failed test will be reloaded N times (in total it will take N * times of time)

  4. UI Trigger – a kind of UI WebElement, a real delay trigger (delay trigger) on the page, clearly making it clear that the event has occurred. Surely most tests have a feature to fall when you click on a certain element. The problem is that it is not always clear whether the event has completed its action or has the wrong attribute. For example, downloading files, using the almighty Selenide downloaded the file, but how to understand that the file was completely transferred from the server? Setting sleep to 10 seconds is not an option. Programmers should be explicitly urged to install a spinner or loading indicator on the web page.

  5. JS Injection – I’ll write a word about this. Not used in practice. You can inject a web element with a css class or change the value of an attribute. For especially desperate cases.

Flock tests are unstable tests. At times they fall, giving a false-positive result. Many factors influence, javaScript (not fully rendered, pop-up windows, scrolling, overlapping with another layer or web element), framework, hardware speed, system crash, small/fullscreen screen, network.

Disable script execution

Sometimes it is very useful to disable the execution of js code in the script (too fast animation or element disappearance). You can do this directly from devtools.

F12
Ctrl+Shift+P (Cmd+Shift+P)
disable JavaScript

Basic Helper. Hot keys for IDE

Hotkeys are an indispensable assistant in any situation. Don’t make life difficult for yourself, learn them.

# Переход между вкладками
ALT + (->, <-)

# Чтобы открыть любой файл
CTRL + SHIFT + N

# Find in files
CTRL + SHIFT + F

# Format current page
CTRL + ALT + O
CTRL + ALT + L

Locator generators. Useful webElement Locator generators

It is useful and very convenient to use generator functions to format locators, here are some examples:

  public static String insertIntoTitleStartsWith(String textInTitle) {
    return String.format("*[title^='%s']", textInTitle);  // ^ нужно для поиска элементов, которые содержат атрибут начинающийся с переданного текста
  }

  public static String insertIntoTitle(String textInTitle) {
    return String.format("*[title="%s"]", textInTitle);
  }

  public static String insertIntoAttribute(String attribute, String value) {
    return String.format("*[%s="%s"]", attribute, value);
  }

A few more goodies

Text with spaces, collection filtering, and pseudo-classes

/* Java Core. Разница в проверке пробела: */
StringUtils.isBlank(" ") = true
StringUtils.isEmpty(" ") = false
  
/* Коллекция элементов, не входящих в заданный класс */
ElementsCollection notCheckedCheckboxes = $$("div.checkboxes").filterBy(not(cssClass("checked")));

/* Проверка что чекбокс включен */
$("input:checked").should(exist)

Finally

I hope you were able to pick up something useful to use. Try, experiment, interact with the team, because this is the most important thing. I will be glad to any suggestions and comments on this article.

I express my gratitude to every developer who was with me on the project. I know I ping you a lot, but your help and participation in testing is invaluable. This article is a small offshoot of that same help.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *