Есть ли способ написать вызов findElement, передав строковое значение для type

#c# #selenium

#c# #selenium

Вопрос:

В настоящее время я пишу тест пользовательского интерфейса Selenium для нашего нового транзакционного веб-сайта, однако при настройке решения я пытаюсь найти более эффективный способ создания метода поиска моего элемента без дублирования кода.

В идеале я хочу создать что-то похожее на это:

     public void SearchForElement(IWebDriver driver, string elementType, string elementReference)
    {
        driver.FindElement(By.Id(elementReference));
    }
  

Где ‘Id’ — это значение переменной ‘ElementType’

В предыдущих решениях я сделал следующее:

             if (elementType == "Id")
            {
                returnElement = driver.FindElement(By.Id(elementReference));
            }

            else if (elementType == "Name")
            {
                returnElement = driver.FindElement(By.Name(elementReference));
            }
            else if (elementType == "CssSelector")
            {
                returnElement = driver.FindElement(By.CssSelector(elementReference));
            }
            else if (elementType == "XPath")
            {
                returnElement = driver.FindElement(By.XPath(elementReference));
            }
            else if (elementType == "ClassName")
            {
                returnElement = driver.FindElement(By.ClassName(elementReference));
            }
  

Однако, как вы можете видеть, последнее фактически является той же строкой кода, которая различается только типом.

Любая помощь / совет будут высоко оценены.

Комментарии:

1. Есть ли причина, по которой вы хотите передать строку для типа?

2. Поскольку тесты пользовательского интерфейса пишутся параллельно с разработкой нашего транзакционного сайта (не идеально, я знаю) Мне проще поддерживать массив элементов, которые я использую, однако, поскольку практически отсутствует согласованность в отношении того, имеют ли они связанный идентификатор, я обнаружил, что мне приходится использовать множество разных типов. Фрагмент массива, который я использую, выглядит так: { «ppsBuyFlow», «emailRegister», «Id», «Email» }, {«ppsBuyFlow», «emailRegisterGo», «XPath», «/html/body /div[6]/div/form/div/div /div[2]/input» },

3. Возможно, было бы лучше вместо этого создать модели страниц. Вы можете определять методы и свойства, не зная точных локаторов. Что-то вроде private IWebElement EmailField => throw new NotImplementedException(); дает вам достаточно для написания некоторого кода.

Ответ №1:

Поскольку тесты пользовательского интерфейса пишутся параллельно с разработкой нашего транзакционного сайта (не идеально, я знаю) Мне проще поддерживать массив элементов, которые я использую

Нет ничего плохого в написании автоматических тестов параллельно с разработкой. На самом деле, это идеальный способ сделать это. На самом деле у вас гораздо большая проблема, чем вопрос, который вы задаете. Ваша проблема может быть решена с помощью другой архитектуры для ваших тестов. Инкапсуляция поведения автоматизации в объектной модели страницы Selenium позволяет вам частично создавать классы, которые могут использовать другие тестировщики, но отложить такие вещи, как определение локаторов, до тех пор, пока у вас не будет пользовательского интерфейса для работы.

В качестве примера представьте, что вы автоматизируете пользовательский интерфейс для приложения со списком задач. Пользовательский интерфейс еще не создан, но это не мешает вам написать тест:

 todoList = new TodoListPageModel(driver);

todoList.Add("Pay the electric bill");

CollectionAssert.Contains(todoList.GetItems().ToList(), "Pay the electric bill");
  

Ваша модель страницы будет выглядеть следующим образом:

 public class TodoListPageModel
{
    private readonly IWebDriver driver;

    private IWebElement AddButton => throw new NotImplementedException();
    private IWebElement TodoTextField => throw new NotImplementedException();
    private IEnumerable<IWebElement> Items => throw new NotImplementedException();

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

    public void Add(string todo)
    {
        TodoTextField.SendKeys(todo);
        AddButton.Click();
    }

    public IEnumerable<string> GetItems()
    {
        return Items.Select(item => item.Text.Trim());
    }
}
  

Свойства, которые ссылаются на элементы или коллекции элементов, могут вызывать исключение NotImplementedException, пока у вас не будет пользовательского интерфейса. Затем вы можете реализовать эти свойства, используя правильный локатор, и запустить тесты.

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