Используйте объект внутри попытки/улова вне попытки/улова

#c# #selenium #selenium-webdriver #selenium-chromedriver

Вопрос:

Мне нужен способ использовать объект или переменную, которая находится внутри попытки/улова, вне попытки/улова.

Я провожу автоматические тесты с селеном на веб-странице blazor.

На веб-странице есть элемент, который динамически меняет свое имя.

Моя идея сейчас такова: в 99 из 100 случаев он всегда находит вызываемую переменную selector , что означает , что никаких исключений не возникает. В этом случае я хочу использовать объект Field за пределами try/catch.

Но в одном случае на веб-странице есть один элемент //div[@class='ql-editor']//p , который меняет свое имя во время теста на //div[@class='ql-editor ql-blank']//p . Теперь, прежде чем тест выдаст мне исключение, он должен проверить, //div[@class='ql-editor ql-blank']//p видно ли оно.

Если да, то я хочу использовать объект Field из блока catch за пределами try/catch. Если нет, это должно вызвать у меня исключение

ПРИМЕЧАНИЕ: Я осознаю тот факт, что, возможно, способ, которым я думаю решить эту проблему, не самый лучший. Я просто хочу предотвратить создание другого метода только для 1 из 100 случаев.

         try
        {
            IWebElement Field = webDriver.FindElement(By.XPath(selector));
            Field.SendKeys(textToType);
        }
        catch (Exception e)
        {
            IWebElement Field = webDriver.FindElement(By.XPath("//div[@class='ql-editor ql-blank']//p"));
            Field.SendKeys(textToType);
        }

        string checkText = Field.GetAttribute("value");
        string checkInstruction = Field.Text;
 

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

1. Просто объявите Field вне попытки, но без значения: IWebElement Field; . Примечание. Вы также можете переместить вызов в SendKeys после попытки…поймать… чтобы избежать дублирования кода.

2. спасибо, я попробую

3. Я отправил его в качестве ответа на случай, если я не был ясен 🙂

Ответ №1:

Что сказал РБ…

     IWebElement field;
    try
    {
        field = webDriver.FindElement(By.XPath(selector));
    }
    catch
    {
        field = webDriver.FindElement(By.XPath("//div[@class='ql-editor ql-blank']//p"));
    }
    field.SendKeys(textToType);

    string checkText = field.GetAttribute("value");
    string checkInstruction = field.Text;
 

Иногда, когда вы применяете этот шаблон, вы можете увидеть сообщения компилятора «использование неназначенной локальной переменной …» — в этих случаях вы можете назначить null или default при объявлении, или вы можете назначить какое-либо значение, подходящее по умолчанию:

     IWebElement field = "some sensible default";
    try{
      ...
 

В комментариях разумно указано, что вы получаете это сообщение, потому что C# может видеть некоторый путь в вашем коде, где переменной никогда не присваивалось какое-либо значение. Это может быть то, чего вы ожидаете, а может и нет; только вы можете это знать. Если вы смотрите на какой-то код и думаете: «к тому времени, когда я достигну строки X, переменная Y определенно будет иметь какое-то полезное значение», а C# говорит вам об обратном, это стоит проверить еще раз. Хотя это не идеально/не погружает глубоко во все возможные сценарии (некоторые вещи не могут быть известны во время компиляции, а другие не стоит вычислять), вы должны убедиться, что ваше значение присвоено, если вы ожидаете, что к этому времени оно будет иметь значение

ps; пожалуйста, объявите местных жителей с помощью camelCase, и вы можете опустить e тип исключения in Exception e или даже весь тип исключения после улова, если вы ловите все и ничего не делаете с исключением

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

1. «вы можете увидеть «использование неназначенной локальной переменной …» сообщения компилятора» стоит обратить пристальное внимание на эти сообщения — они часто говорят вам, что вы забыли назначить переменную на одном из возможных путей в программе. Простое назначение null приведет к исчезновению ошибки компилятора, но рискует просто превратить ее в ошибку во время выполнения (назначение значения по умолчанию, конечно, может быть совершенно правильным — просто внимательно рассмотрите желаемое поведение).

Ответ №2:

Просто объявите переменную вне try...catch... блока.

 IWebElement Field;
try
{
     Field = webDriver.FindElement(By.XPath(selector));
}
catch (Exception e)
{
    Field = webDriver.FindElement(By.XPath("//div[@class='ql-editor ql-blank']//p"));
}

Field.SendKeys(textToType);
string checkText = Field.GetAttribute("value");
string checkInstruction = Field.Text;
 

Ответ №3:

Два других ответа являются «легким» ответом, но, на мой взгляд, неправильным ответом. Ваш опубликованный код не соответствует рекомендациям, которые позволили бы очистить большую часть кода и устранить проблему, о которой вы спрашиваете.

Есть два лучших подхода к тому, что вы пытаетесь сделать.

  1. Предпочтительным способом было бы создать локатор, который проверяет и selector то, и другое, и ql-blank случай. Я не могу показать вам это, потому что вы не опубликовали определение selector . В качестве примера я покажу вам использование двух локаторов, которые вы опубликовали. Вместо использования XPath здесь лучшим выбором является CSS-селектор. Синтаксис проще и легче читается, он быстрее выполняется и лучше поддерживается. Если вам нужна дополнительная информация, посмотрите несколько видеороликов seleniumconf yt, в которых авторы рассказывают о локаторах.

    Вот два пути XPath, которые вы предоставили.

     //div[@class='ql-editor']//p
    //div[@class='ql-editor ql-blank']//p
     

    Давайте преобразуем эти два в селекторы CSS.

     div.ql-editor p
    div.ql-editor.ql-blank p
     

    а теперь объедините их в один CSS-селектор с помощью оператора ИЛИ (,).

     div.ql-editor p, div.ql-editor.ql-blank p
     

    Теперь вы можете обновить свой код до

     By locator = By.CssSelector("div.ql-editor p, div.ql-editor.ql-blank p");
    IWebElement Field = webDriver.FindElement(locator);
    Field.SendKeys(textToType);
    
    string checkText = Field.GetAttribute("value");
    string checkInstruction = Field.Text;
     

    Как вы можете видеть, этот код намного проще и выполняет то же самое.

  2. Другим подходом, который следует рекомендациям по работе с элементами, которые могут не существовать, было бы использование .FindElements() и проверка пустого списка вместо использования исключений.
     ReadOnlyCollection<IWebElement> Field = webDriver.FindElements(selector);
    if (!Field.Any())
    {
        Field = webDriver.FindElements(By.XPath("//div[@class='ql-editor ql-blank']//p"));
    }
    Field.ElementAt(0).SendKeys(textToType);
    
    string checkText = Field.GetAttribute("value");
    string checkInstruction = Field.Text;
     

    Этот метод не совсем такой чистый, как метод 1, но это лучший и более чистый подход по сравнению с использованием исключений.