Released Selenide 6.2.0

Released Selenide 6.2.0

Soft asserts, hard iterators

Happy New Year, people!

We released Selenide 6.2.0.

Let’s look into this year’s first release.

Pour some tea and let’s go!

Added link “<Click to see difference>” for most of Selenide assertion errors

As you remember, in Selenide 5.25.0 we added Test4J support. As a result, Selenide assertion errors got a link “<Click to see difference>” in IDE which allows to easily compare expected and actual values in case of test failure.

At that moment we didn’t have enough time to refactor all the assertion errors, and some of them didn’t get the link.
Now we added the link to all the errors.

See issue 1589 and PR 1676.

Replaced $$.iterator() by $$.asDynamicIterable() and $$.asFixedIterable()

Wow, what an old sore we have fixed!

Selenide has method $$ for a collection of web elements. It returns instance of class ElementsCollection.
Initially, it should have only one method $$.shouldHave(<condition>). When you want to verify the collection - pass it the needed condition. If you didn’t find a needed condition - create your own, it’s easy.

The mistake

But I did a mistake at that moment. I inherited class ElementsCollection from AbstractList<SelenideElement>. I later regretted this decision many times.

What happened, you may ask? People started abusing the collections.

  • For example, they wanted to iterate the collection elements (and it occasionally was possible because of extending AbstractList).
  • they expected that the collection elements will be reloaded during the iteration (because Selenide had been updating all other web elements during checks & re-tries).
  • In addition to the questionable test design, this also caused performance problems, because at every iteration step Selenide must reload the entire collection. And it can be slow, especially if there are many elements in the collection, or the collection is being filtered: $$("div").filter(visible).filterBy(text("Hello")).

The dilemma

The dilemma turned out:

  • some people wanted Selenide to reload collection elements during the iteration (because it helps to avoid StaleElementException etc when the elements appear and disappear during the iteration);
  • other people didn’t want Selenide to reload the elements because it makes tests faster on big collections.

Whichever option we choose, we won’t please everyone.

The solution

Finally, we figured out how to solve this dilemma. We deprecated all these methods like $$.iterator() which were occasionally inherited from AbstractList. As a replacement, we suggest two new methods. You can choose one of them depending on your needs:

  • $$.asDynamicIterable() - reload the elements during the iteration. Might be slow on big collections.
  • $$.asFixedIterable() - doesn’t reload the elements. May be faster, but will not get updates if elements appear/disappear during the iteration.

The recommendation

Which one I recommend to you, you may ask?


In the end, let me remind that well-designed test should not have loops, ifs etc. You must know how many elements are expected, and which properties they are expected to have. Just verify those properties.

Instead of iteration, it’s always better to create your custom CollectionCondition. It’s easy.

See issue 797 and PR 1688.

Fixed SoftAssert to avoid failing a test

in a rather rare situation:

  1. when soft assert listener/rule/extension is added to a test, but
  2. soft asserts are disabled, and
  3. there was an assertion error raised and caught during the test execution (try/catch).

It sounds like a design smell. Probably such test should be fixed. :(

But still, we fixed the Selenide soft assert listener. Now it doesn’t fail the test if soft assertions are disabled.

Uh, well, you sometimes throw up unexpected problems, dear users … :)

See issue 1646 and PR 1680.

We fixed soft asserts to include all the errors

There was one more rare problem with soft asserts. Image the situation:

  1. You have soft asserts enabled;
  2. During the test execution, some Selenide assertion errors were raised (and caught by the listener);
  3. But there was also some other assertion error (like NPE or assertEquals(2, 3)).

In this case, Selenide soft assert listener failed the test (which is correct), but showed only Selenide assertion errors (#2) and lost the “other” error (#3).

Now the listener got smarter: it merges all the assertion errors.

See issue 1661 and PR 1679.

We added locator to some of Selenide assertion errors

Another small improvement.

We added a locator to some of Selenide assertion errors.
For example, if previously you could see an error like this:

“Invalid element state: Cannot change invisible element”

then now you will see the improved error message:

“Invalid element state [.btn.btn-primary]: Cannot change invisible element”

Upgraded BrowserUpProxy from 2.1.2 to 2.1.3

Note that version 2.1.3 is a fork of the original BrowserUpProxy. The authors announced the end of support, and the volunteers took over and released version 2.1.3 from the fork.

We will monitor the situation. Ideally, it would be great to switch from BrowserUpProxy to mitmproxy. Are there volunteers?

See PR 1678.

Upgraded TestNG from 7.4.0 to 7.5

Changelist is quite impressive.

See PR 1682.

Happy New Year, my friends!
I wish you stable tests and beautiful reports!

Andrei Solntsev