Мы только начали использовать Serenity-BDD с шаблоном ScreenPlay. В настоящее время мы боремся с тем, как избежать дублирования кода в задачах.
Чтобы привести простой пример:
У нас есть страница для компаний. На нем у нас есть таблица с компаниями. Также есть кнопка Создать компании и текстовое поле для фильтрации по названию компании. Затем таблица будет отфильтрована.
Сначала я определил следующие задачи:
- CreateCompany
- FindCompany
- VerifyCompany
- EditCompany
Они были автономными, но имели дублирование кода:
- CreateCompany нажимает кнопку «Создать компанию» и затем заполняет поля во всплывающем окне. EditCompany вводит название компании в фильтре, выбирает компанию в таблице и затем заполняет поля во всплывающем окне. Фактическое редактирование всплывающего окна было дублирующим кодом
- Аналогично, было дублирование кода между FindCompany и EditCompany для нахождения компании
Так что теперь я изменил задачи так, чтобы они должны былицепочка:
- Чтобы создать компанию, вам нужно позвонить CreateCompany + EditCompany
- Чтобы изменить компанию, вам нужно позвонить FindCompany + EditCompany
Но это не так по отношению к шаблону ScreenPlay. Итак, основной вопрос: на каком уровне должны быть определены задачи? Я думаю, что идея шаблона ScreenPlay заключается в том, что они являются пользовательскими задачами, поэтому они должны быть автономными.
Чтобы выяснить, почему это проблема, избегающая дублирования кода, ниже приведен небольшой фрагмент нашего кода Scala дляЗадача CreateCompany (не самодостаточная):
override def performAs[T <: Actor](actor: T): Unit = {
// Create specific code
actor should eventually(seeThat(CompanyPage.CreateClickable, is(true)))
.waitingForNoLongerThan(10)
.seconds()
actor.attemptsTo(Click.on(NEW_COMPANY_BUTTON))
actor can eventually(seeThat(CompanyPage.CreatePopupDisplayed, is(true)))
.waitingForNoLongerThan(10)
.seconds()
// Code shared by Create and Edit
actor.attemptsTo(
Enter.theValue(company.name.get).into(NAME_FIELD),
SelectFromOptions.byVisibleText(company.country.get.toString).from(COUNTRY_SELECT)
)
actor should eventually(seeThat(CompanyPage.AccountManagerClickable, is(true)))
.waitingForNoLongerThan(10)
.seconds()
actor.attemptsTo(
SelectFromOptions.byVisibleText(company.accountManager.get).from(ACCOUNT_MANAGER_SELECT),
Enter.theValue(company.sector.get).into(SECTOR_FIELD),
SelectFromOptions.byVisibleText(company.role.get.toString).from(POWER_MARKET_ROLE_SELECT),
Click.on(SAVE_BUTTON)
)
Понятия не имею, как избежать дублирования кода в стиле программирования Fluent. Мы попытались переместить общий код в класс Mixin:
override def performAs[T <: Actor](actor: T): Unit = {
Enter.theValue(company.name.get).into(NAME_FIELD)
SelectFromOptions.byVisibleText(company.country.get.toString).from(COUNTRY_SELECT)
actor should eventually(seeThat(CompanyPage.AccountManagerClickable, is(true)))
.waitingForNoLongerThan(10)
.seconds()
Enter.theValue(company.accountManager.get).into(ACCOUNT_MANAGER_SELECT)
Enter.theValue(company.sector.get).into(SECTOR_FIELD)
SelectFromOptions.byVisibleText(company.role.get.toString).from(POWER_MARKET_ROLE_SELECT)
Click.on(SAVE_BUTTON)
}
Он скомпилирован отлично, но при вызове из метода actor.attemptsTo (Selenium ничего не делал на странице. Ничего не было заполнено. ОБНОВЛЕНИЕ: в другом месте у меня теперь есть actor.attemptsTo (с несколькими действиями. Я вижу, что они не заполняются, когда я их отлаживаю, а заполняются немного позже. Так что класс mixin может работать, но не будетидеально с точки зрения отладки.
Также мне не понравилось, что во избежание дублирования кода нам пришлось создавать дополнительные классы с большим количеством шаблонного кода.