如果找不到元素,不确定如何使用 try catch 处理异常

Not sure how to handle exceptions using try catch if element was not found

我正在尝试通过清除输入的用户名字段来处理登录页面上的错误消息。

这是我的代码:

using OpenQA.Selenium;
using System;
using System.Linq.Expressions;
using TestProject.Common.Extensions;
using TestProject.SDK;
using TestProject.SDK.Tests;
using TestProject.SDK.Tests.Helpers;

namespace SecondTest
{
    public class LoginTest : IWebTest
    {
        public object Assert { get; private set; }
        public object TimeUnit { get; private set; }
        public object InvalidInputErrorTxt { get; private set; }
        public bool IWebelement { get; private set; }
        public bool ErrorMsg { get; private set; }

        public ExecutionResult Execute(WebTestHelper helper)
        {
            var driver = helper.Driver;
            var URL = "https://www.office1.bg/login";
            driver.Navigate().GoToUrl(URL);
            driver.Manage().Window.Maximize();
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            driver.FindElementById("CybotCookiebotDialogBodyLevelButtonAccept").Click();
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            //Login
            Pages.LoginPage LoginPage = new Pages.LoginPage(driver);
            LoginPage.PerformLogin("atanas.grudev1@gmail.com", "123456789");
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            try
            {
                IWebElement Level = driver.FindElementByClassName("corporal-page-list-item");
                if (Level.Displayed)
                {
                    Level.Click();
                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
                    driver.FindElementByClassName("corporate-login-button-wrapper").Click();
                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
                    return ExecutionResult.Passed;
                }
                else
                {
                    IWebElement ErrorMsg = driver.FindElementByXPath("//*[@id='loginForm']/div/div[1]");
                    if (ErrorMsg.Displayed)
                    {
                        LoginPage.TxtUserName.Clear();
                        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
                        return ExecutionResult.Failed;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return ExecutionResult.Passed;
        }       
            }  
        }

开头的ExecutionResult好像需要returnExecutionResult.Passed/Failed;在代码的末尾,但由于我尝试 - 捕获我不确定如何获得正确的结果。最终目标是: 如果输入了有效凭据,则应执行第一个 if 语句中的代码并获得通过结果。 如果输入的凭据无效,网站将抛出错误,如果错误出现在屏幕上,则应清除用户名字段的输入并获得失败结果。

提前致谢!

几点建议:

  1. 通常,您希望尽可能避免使用 try-catch 来控制代码流。在这种情况下,您可以使用 driver.FindElements()(注意复数 ElementS)并检查空列表以避免在找不到元素时抛出异常。根据 the docs.

    ,这是最佳实践

    findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.

  2. ImplicitWait设置超时只需要完成一次。设置后,每次搜索元素时都会自动应用该超时。它实际上并没有在调用时等待......我想你可能将它与 WebDriverWait?

    混淆了
  3. Selenium 贡献者不推荐使用 ImplicitWait。每次需要等待时,您都应该使用 WebDriverWait

  4. 我建议您研究并使用页面对象模型。如果做得好,它将为您节省大量代码重用时间,使您的项目更有条理,并使您的测试代码更清晰。看起来您正在尝试在 LoginPage.PerformLogin() 调用中使用诸如页面对象之类的东西,但是您所有的 driver.FindElement() 调用都应该在适当的页面对象中,并且每个“页面”应该有一个页面对象。

这是实施前两个建议后的代码。如果你愿意,我会让你做#3 和#4。我删除了 try-catch,添加了新的 if,并删除了除第一个 ImplicitWait 集之外的所有内容。

using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Linq;
using TestProject.Common.Extensions;
using TestProject.SDK;
using TestProject.SDK.Tests;
using TestProject.SDK.Tests.Helpers;

namespace SecondTest
{
    public class LoginTest : IWebTest
    {
        public object Assert { get; private set; }
        public object TimeUnit { get; private set; }
        public object InvalidInputErrorTxt { get; private set; }
        public bool IWebelement { get; private set; }
        public bool ErrorMsg { get; private set; }

        public ExecutionResult Execute(WebTestHelper helper)
        {
            var driver = helper.Driver;
            var URL = "https://www.office1.bg/login";
            driver.Navigate().GoToUrl(URL);
            driver.Manage().Window.Maximize();
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            driver.FindElementById("CybotCookiebotDialogBodyLevelButtonAccept").Click();

            //Login
            Pages.LoginPage LoginPage = new Pages.LoginPage(driver);
            LoginPage.PerformLogin("atanas.grudev1@gmail.com", "123456789");

            IReadOnlyCollection<IWebElement> level = driver.FindElementsByClassName("corporal-page-list-item");
            if (level.Any() && level.ElementAt(0).Displayed)
            {
                level.ElementAt(0).Click();
                driver.FindElementByClassName("corporate-login-button-wrapper").Click();

                return ExecutionResult.Passed;
            }

            IReadOnlyCollection<IWebElement> errorMsg = driver.FindElementsByXPath("//*[@id='loginForm']/div/div[1]");
            if (errorMsg.Any() && errorMsg.ElementAt(0).Displayed)
            {
                LoginPage.TxtUserName.Clear();
                return ExecutionResult.Failed;
            }

            return ExecutionResult.Passed;
        }
    }
}

关于新代码的一些注意事项,您可能以前没有见过。

  1. .Any() 在 LINQ 中等同于 .Count > 0。如果列表不为空,则 returns true,否则 false
  2. .ElementAt() 是一种 LINQ 方法,允许您通过索引访问集合的成员。注意:尽管它的名称中有“Element”,但它与 WebElement 或 Selenium 无关。

如果您有任何问题,请告诉我。