Я работаю над приложением со многими похожими экранами данных / CRUD.Я использую Selenium с шаблоном объектов страницы для навигации в приложении, а матери объектов - для создания предопределенных тестовых данных, особенно для форм с множеством входных данных.
При написании файлов объектов мне пришло в голову, что тесты настолько похожи друг на друга и что должна быть возможность обобщить некоторые общие шаги ради повторного использования и СУХОГО состояния.Объект страницы DataTable был прост, поскольку селекторы одинаковы для всех страниц.Поэтому я создал DataTable
объект страницы, который имеет необходимые операции для фильтрации, выбора строк и т. Д. Я использовал DI с помощью механизма ввода контекста Specflow.
Пример:
Scenario: List and search Users
When I type 'test@test.test' in filter
Then I should only see items with 'email' = 'test@test.test'
И шаги:
[Binding]
public class DataTableSteps
{
private DataTable _page;
public DataTableSteps(DataTable page) => _page = page;
[When(@"I type '(.*)' in filter")]
public void WhenITypeInFilter(string value) {
_page.FilterSearch (value);
}
[Then(@"I should see items with '(.*)' = '(.*)'")]
public void ThenIShouldSeeAListWhereContains(string column, string value)
{
_page.VisibleInTable(column, value).Should().BeTrue();
}
}
Проблема в том, что я не могу найти хороший дизайн, когда пытаюсь создать общий класс шагов WebFormSteps
, который обрабатывает данные формы для заполнения различных входов различными объектами страницы WebForm
,Я хочу сделать следующее:
Scenario: Add User
When I go to '/Users'
When I create a 'validUser' Item #'validUser' comes from the object mother
Then 'validUser' should be added
И использовать те же самые шаги и определения шагов, например, для продукта:
Scenario: Add Product
When I go to '/Products'
When I create a 'validProduct' Item
Then 'validProduct' should be added
Я думал об использовании интерфейсов или абстрактных классов и позволял NewUserInputWebForm
объект страницы и UserMother
для их реализации, однако я не смог найти способ ввести правильный конкретный тип во время выполнения.(Я решил поместить конкретные объекты-матери в связанные объекты страницы, что означало бы на одну зависимость меньше от шага, но я не мог оправдать добавление объекта-матери к такому не связанному классу, то есть к объекту страницы).
[Binding]
class WebFormSteps
{
IWebFormObject formObject;
IObjectMother objectMother;
public WebFormSteps(IWebFormObject formObject, IObjectMother objectMother)
{
this.formObject = formObject;
this.objectMother = objectMother;
}
[When(@"I create a '([^']*)' item")]
public void WhenICreate(string exampleName)
{
form = objectMother.Create(exampleName);
formObject.FillForm(form);
formObject.Submit();
}
}
Одна вещь, которая пришла мне в голову, - это использовать интерфейсную область с крюком и зарегистрировать интерфейс с нужными объектами, однако в этом случае будет множество меток и методов подключения.Точно так же я могу зарегистрировать тип на каком-то другом шаге, например When I go to '/Users'
step, но это усложнит ситуацию еще больше.Можно использовать отражение или указать имя типа в определении шага: When I create a 'User' named 'validUser'
, но это сделает хрупкие испытания еще более хрупкими.Более того, тесты стали бы слишком техническими, а не огурцовыми.
Есть ли хороший способ добиться этого?Я даже не уверен, является ли такой подход хорошей практикой (включая таблицу данных), потому что я не смог найти более тривиальных примеров такого использования.Должен ли я придерживаться специализированных шагов, таких как:
Scenario: Add User
When I go to '/Users'
When I create a user named 'validUser'
Then 'validUser' should be added to users