#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:
Два других ответа являются «легким» ответом, но, на мой взгляд, неправильным ответом. Ваш опубликованный код не соответствует рекомендациям, которые позволили бы очистить большую часть кода и устранить проблему, о которой вы спрашиваете.
Есть два лучших подхода к тому, что вы пытаетесь сделать.
- Предпочтительным способом было бы создать локатор, который проверяет и
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;
Как вы можете видеть, этот код намного проще и выполняет то же самое.
- Другим подходом, который следует рекомендациям по работе с элементами, которые могут не существовать, было бы использование
.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, но это лучший и более чистый подход по сравнению с использованием исключений.