Как избежать дублирования кода в задачах Serenity-BDD с помощью Fluent Programming? - PullRequest
0 голосов
/ 22 октября 2019

Мы только начали использовать 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 может работать, но не будетидеально с точки зрения отладки.

Также мне не понравилось, что во избежание дублирования кода нам пришлось создавать дополнительные классы с большим количеством шаблонного кода.

...