Определение шага Specflow - совместное использование функций, когда задействованы объекты страницы - PullRequest
1 голос
/ 12 февраля 2020

У меня есть несколько файлов объектов, которые должны утверждать предварительно заполненные данные на веб-странице - каждый файл объектов имеет свой собственный файл определения шага

, например, в файле определения шага функции клиента:

[Then(@"I expect all fields on the screen populated with Customer Details from the Database")]
public void PopulatedWithCustomerDetailsFromTheDatabase ()
{
  foreach (var entry in dataDictionary)
  {
       Assert.That(pages.CustomerPage.GetText(entry.Key), Is.EqualTo(entry.Value));
  }
}

в файле определения шага компании:

[Then(@"I expect all fields on the screen populated with Company Details from the Database")]
public void PopulatedWithCompanyDetailsFromTheDatabase()
{
    foreach (var entry in dataDictionary)
    {
      Assert.That(pages.CompanyDetailsPage.GetText(entry.Key), Is.EqualTo(entry.Value));
    }
}

Оба используют соответствующий класс объекта страницы для получения текста со страницы и подтверждения его правильности. Было рекомендовано, чтобы я не разделял определения шагов, как это, поскольку они используют разные объекты страницы, с которыми я согласен. Проблема в том, что мне нужно будет сделать это на следующих 50+ страницах: CustomerPage, CompanyDetailsPage, StockPage, DeliveryPage и т. Д. c ...

Любые советы о том, как мне это структурировать, чтобы у меня было больше общего в Step Defs? - должен быть лучший способ, я просто дублирую код, но изо всех сил пытаюсь визуализировать решение с архитектурной точки зрения.

Действия, общие для многих страниц, должны быть инкапсулированы, поскольку собственные модели страниц и модели страниц могут быть составлены многостраничных моделей - как этого можно достичь?

Чтобы пояснить, что каждая страница отличается, поэтому в дополнение к описанным выше шагам для функции «Адресная страница» у меня есть шаг def:

[Then(@"I expect all fields on the screen populated with AddressDetails from the Database")]
public void PopulatedWithAddressDetailsFromTheDatabase()
{
    foreach (var entry in dataDictionary)
    {
      Assert.That(pages.AddressDetailsPage.GetText(entry.Key), Is.EqualTo(entry.Value));
    }
}

с полями, такими как адресная строка1, адресная строка 2 и т. д. c ....

и функция «Страница запаса» с шагом по умолчанию:

[Then(@"I expect all fields on the screen populated with Stock from the Database")]
public void PopulatedWithStockFromTheDatabase()
{
    foreach (var entry in dataDictionary)
    {
      Assert.That(pages.StockPage.GetText(entry.Key), Is.EqualTo(entry.Value));
    }
}

с полями списка запасов и т. д. c ... для 50 разных страниц

1 Ответ

2 голосов
/ 12 февраля 2020

Вы можете параметризовать имя страницы и вести словарь объектов страницы.

Then I should see the following details on the "Stock" page:
    | Field | Value |
    | ...   | ...   |

Then I should see the following details on the "Company Details" page:
    | Field | Value |
    | ...   | ...   |

Вам понадобится каждый из ваших объектов страницы для реализации одного и того же интерфейса, чтобы вы могли хранить их в словаре и вызовите метод GetText для них в определении шага:

public interface IReadOnlyPageModel
{
    string GetText(string key);
}

Затем реализуйте этот интерфейс в своих моделях страниц:

public class StockDetailsPage : IReadOnlyPageModel
{
    // stuff specific to the stock details page

    public string GetText(string key)
    {
        // based on key, return text
    }
}

public class CompanyDetailsPage : IReadOnlyPageModel
{
    // stuff specific to the company details page

    public string GetText(string key)
    {
        // based on key, return text
    }
}

Тогда вам понадобится словарь на вашем шаге определение класса и, конечно, определение шага:

[Binding]
public class StepDefinitions
{
    private readonly Dictionary<string, IReadOnlyPageModel> detailsPages;

    public StepDefinitions(IWebDriver driver)
    {
        // Or however you get access to the IWebDriver object
        detailsPages = = new Dictionary<string, IReadOnlyPageModel>()
        {
            { "Stock", new StockDetailsPage(driver) },
            { "Company", new CompanyDetailsPage(driver) }
        };
    }

    [Then(@"Then I should see the following details on the ""(.*)"" page:")]
    public void ThenIShouldSeeTheFollowingDetailsOnThePage(string pageName, Table table)
    {
        var page = detailsPages[pageName];

        foreach (var row in table.Rows)
        {
            Assert.That(page.GetText(row["Field"]), Is.EqualTo(row["Value"]));
        }
    }
}

Если вы заметили, что все ваши локаторы элементов, похоже, следуют шаблону, вы можете создать общую модель страницы c:

public class GenericPageModel : IReadOnlyPageModel
{
    private readonly IWebDriver driver;

    public GenericPageModel(IWebDriver driver)
    {
        this.driver = driver;
    }

    public string GetText(string key)
    {
        return driver.FindElement(By.XPath($"//caption(contains(., 'Details')]/..//tr[contains(., '{key}')]/td[2]")).Text;
    }
}

И измените определение шага, чтобы использовать общую модель страницы c, если запись не найдена в поле detailsPages.

var page = detailsPages.ContainsKey(pageName)
         ? detailsPages[pageName]
         : new GenericPageModel(driver); // Or however you get access to your IWebDriver object
...