В чём разница между .shouldHave (text()) и .shouldHave(texts())?

Проблема (Вопрос) заключается в том, что я не понимаю, почему в примере 1 тест проходит, а в примере 2, тест падает с ошибкой “Texts size mismatch”
Хотелось бы, что бы кто-то опытный пояснил, почему не получается пройти тест примером 2 и можно ли так то его изменить, что бы он сработал.
Пример 1

public class Temp2 {
    @Test
    public void tempTemp(){
        Configuration.holdBrowserOpen = true;
        open("https://ya.ru");
        $("[role='combobox']").setValue("привет").pressEnter();
        ElementsCollection results = $$(byXpath("//li[@class='serp-item serp-item_card']"));
        for (SelenideElement element : results) {
            element.shouldHave(text("привет"));
        }
    }
}

Пример 2

public class Temp {
    @Test
    public void tempTemp(){
        Configuration.holdBrowserOpen = true;
         open("https://ya.ru");
        $("[role='combobox']").setValue("привет").pressEnter();
        ElementsCollection results = $$(byXpath("//li[@class='serp-item serp-item_card']"))
                .shouldHave(CollectionCondition.texts("привет"));
    }
}

Версия Селениума 6.7.4
Запускаю в Idea под windows.

Из кода селенида

  /**
   * Checks that given collection has given texts (each collection element CONTAINS corresponding text)
   *
   * <p>NB! Ignores multiple whitespaces between words</p>
   */
  @CheckReturnValue
  public static CollectionCondition texts(String... expectedTexts) {
    return new Texts(expectedTexts);
  }

То есть во втором случае у вас в каждом элементе должна быть соответствующая определенная подстрока, и чтобы исправить тест надо

.shouldHave(CollectionCondition.texts("привет", "привет","привет","привет","привет","привет","привет","привет","привет","привет"));

Спасибо. Получается, что для применения метода texts я всегда должен точно знать размер коллекции, для того, что бы знать сколько раз я должен повторить искомое слово.
Выглядит так, что этот метод не для таких случаев.

Пользуйтесь ассертами селенида (ElementsCondition) на коллекциях напрямую, не нужно обходить коллекцию в цикле. Эта конструкция выше вовсе может быть “проигнорирована” (на момент старта цикла коллекция пустая, и тест идет дальше как ни в чем не бывало).

Подскажите пожалуйста, как это сделать в этом конкретном случае.

А какая именно задача стоит?

Задача убедиться, что во всех найденных блоках присутствует искомое слово

Можно использовать CollectionCondition.allMatch:

$$("li").should(allMatch("All elements contain 'zopa'", element -> element.getText().contains("zopa"));

При этом метод сообщит об ошибке, если коллекция будет пустой. А если есть хоть один элемент, и в нем есть искомое слово, то проверка пройдет.

Но имейте в виду, если коллекция очень динамичная, и активно подгружается по частям, то можно словить false positive: допустим, загрузилось 2 элемента, в них есть ключевое слово. Тест как раз проверяет коллекцию, проверка проходит. При этом секунду-две спустя коллекция догружает остальные элементы, и где-то там нет искомого слова (то есть баг).
Поэтому стандартные проверки texts, exactTexts и т.д. хороши тем, что строго проверяют размер ожидаемой коллекции. В случае allMatch надо тоже как-то подстраховаться.

1 лайк