То что вы описываете, это фоновые запросы к серверной части (AJAX). По факту использование этой технологии сейчас становится стандартом при разработке web-приложений. На страницах с такими запросами очень важно отслеживать состояние DOM, вернее следить за тем, чтобы DOM не обновлялся между моментом нахождения элемента и моментом взаимодействия с ним.
Никто не мешает использовать локаторы, которые не завязаны на верстку (осуществлять поиск элементов по уникальным идентификаторам). Мой коментарий больше про то, что ошибка автоматизировать там, где активно меняется бизнес логика. Все остальное лечится тест-дизайном.
На мой взгляд распространенная ошибка — попытка автоматизировать тестирование функциональности, которая активно модифицируется. Автоматизировать нужно устоявшуюся функциональность, тогда и проблем с поддержанием будет меньше.
Странный вопрос. Я использую NUnit и не пользуюсь xUnit. Мне полностью хватает функциональности NUnit и я не ощущаю нехватки каких то фич. Я не предлагаю своим постом сравнивать 2 конкурирующих фреймворка. Просто информирую о важном, на мой взгляд, событии в сфере тестирования ПО.
Посмотрел ваш пример на github и пришел к выводу, что в описанном решении есть несколько архитектурных ошибок.
1. Driver статичен и хранится в BaseObject, от которого наследуются страницы. Когда кол-во ваших тестов перевалит за сотню / тысячу вам захочется запускать их параллельно. И вот тут статичный драйвер даст о себе знать.
2. Хэлперы в вашем описании либо дублируют функциональность страниц, либо отделяют функциональность страницы в отдельный класс. Опять же, при большом кол-ве страниц и тестов, получите много дублирующего кода. Лучше пользоваться прямо классами страниц в тестах. Так тест можно будет читать, т.е. понимать, куда он пошел, что нажал, что получил. Да, возможно иногда нужны вспомогательные классы, для случаев, когда тесты много раз используют метод, который задействует несколько страниц. Но, вероятнее всего, таких методов будет немного.
The public methods represent the services that the page offers
Try not to expose the internals of the page
Generally don't make assertions
Methods return other PageObjects
Need not represent an entire page
Different results for the same action are modelled as different methods
Assert'ы должны быть только в тесте (не в страницах). Хэлперы, в вашем случае, это функциональность страницы. Т.е. метод AssertUserName нужно переделать (и переименовать), чтобы он принимал имя и возвращал true / false. А уже в тесте вызывать например
Assert.IsTrue
У вас есть описание конкретного элемента:
[FindsBy(How = How.XPath, Using = USER_NAME_TEXT_FIELD)]
public IWebElement userNameTextField;
Для чего тогда эта константа? На мой взгляд присвоение лишнее.
public const string USER_NAME_TEXT_FIELD = "//input[@id='email']";
4. Вы создаете драйвер на фичу. В целом это правильно, т.к. позволяет сэкономить время выполнения. Но если у вас появится Alert или в тесте вводятся аутентификационные данные, то все следующие тесты провалятся. Нужно либо создавать драйвер на тест, либо заботиться о непредвиденных сценариях и чистить куки.
В целом, статья интересна. Неплохое исследование и заготовка. Однако чувствуется, что это решение не обкатывалось на большом количестве тестов в реальных проектах.
Есть такое расширение как Selenium WebDriver Support Classes для работы с UI. Там есть набор методов для определения состояния элементов (https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html). В сочетании с wait.until можно безопасно дождаться практически любого состояния страницы. Реализация Selenium WebDriver Support Classes есть и для Java, C# и других популярных языков.
1. Driver статичен и хранится в BaseObject, от которого наследуются страницы. Когда кол-во ваших тестов перевалит за сотню / тысячу вам захочется запускать их параллельно. И вот тут статичный драйвер даст о себе знать.
2. Хэлперы в вашем описании либо дублируют функциональность страниц, либо отделяют функциональность страницы в отдельный класс. Опять же, при большом кол-ве страниц и тестов, получите много дублирующего кода. Лучше пользоваться прямо классами страниц в тестах. Так тест можно будет читать, т.е. понимать, куда он пошел, что нажал, что получил. Да, возможно иногда нужны вспомогательные классы, для случаев, когда тесты много раз используют метод, который задействует несколько страниц. Но, вероятнее всего, таких методов будет немного.
3. Когда речь идет о паттерне Page Object я отталкиваюсь от статьи code.google.com/p/selenium/wiki/PageObjects
Если кратко, то:
Assert'ы должны быть только в тесте (не в страницах). Хэлперы, в вашем случае, это функциональность страницы. Т.е. метод AssertUserName нужно переделать (и переименовать), чтобы он принимал имя и возвращал true / false. А уже в тесте вызывать например
У вас есть описание конкретного элемента:
Для чего тогда эта константа? На мой взгляд присвоение лишнее.
4. Вы создаете драйвер на фичу. В целом это правильно, т.к. позволяет сэкономить время выполнения. Но если у вас появится Alert или в тесте вводятся аутентификационные данные, то все следующие тесты провалятся. Нужно либо создавать драйвер на тест, либо заботиться о непредвиденных сценариях и чистить куки.
В целом, статья интересна. Неплохое исследование и заготовка. Однако чувствуется, что это решение не обкатывалось на большом количестве тестов в реальных проектах.