C# 自动测试从安装程序中列出的代码抛出错误,尽管它已在其他测试中正确执行
我从一组测试中收到一个错误,在这些测试中,它似乎正在查找Setup方法中列出的元素,尽管该方法已被执行,但抛出的错误是: 消息:OpenQA.Selenium.NoSuchElementException:没有这样的元素:无法定位元素:{method:xpath,selector://input[@id='txtCompany']} 会话信息:chrome=71.0.3578.98 驾驶员信息:chromedriver=2.45.615291 ec3682e3c9061c10f26ea9e5cdcf3c53f3f74387,平台=Windows NT 10.0.17763 x8664 我尝试过替换和注释代码,在单击“报告”下拉列表之前,我还添加了返回初始屏幕的额外步骤,尽管这并没有解决问题。类似的代码在发生不同测试的类之外正常工作C# 自动测试从安装程序中列出的代码抛出错误,尽管它已在其他测试中正确执行,c#,selenium,automated-tests,ui-automation,C#,Selenium,Automated Tests,Ui Automation,我从一组测试中收到一个错误,在这些测试中,它似乎正在查找Setup方法中列出的元素,尽管该方法已被执行,但抛出的错误是: 消息:OpenQA.Selenium.NoSuchElementException:没有这样的元素:无法定位元素:{method:xpath,selector://input[@id='txtCompany']} 会话信息:chrome=71.0.3578.98 驾驶员信息:chromedriver=2.45.615291 ec3682e3c9061c10f26ea9e5cd
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using NUnit.Framework;
[SetUp]
public void initalise()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.Manage().Window.Maximize();
//Navigates to the Test DB
driver.Url = "https://TESTWEBSITE.co.uk";
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
//Find Company Text Box and send company name
driver.FindElement(By.XPath("//input[@id='txtCompany']")).SendKeys("COMPANY");
//Find username Text Box and send username
driver.FindElement(By.XPath("//input[@id='txtUsername']")).SendKeys("6969_1");
//Find password and send
driver.FindElement(By.XPath("//input[@id='txtPassword']")).SendKeys("PASSWORD");
//Find Login button and click
driver.FindElement(By.XPath("//input[@id='cmdLogin']")).Click();
}
[Test, Order(1)]
public void reportsStandard()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Standard Reports')]")).Click();
IWebElement ReportType = driver.FindElement(By.XPath("//div[@id='ctl00_ContentPlaceHolder_lstReports']//ul[@class='rlbList']"));
Assert.AreEqual(true, ReportType.Displayed);
}
[Test, Order(2)]
public void reportsPandLCustomer()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[contains(text(),'Home')]")).Click();
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Profit and Loss by Customer')]")).Click();
IWebElement AdvancedFiltering = driver.FindElement(By.XPath("//a[@id='ContentPlaceHolder_cmdAdvancedFiltering']"));
Assert.AreEqual(true, AdvancedFiltering.Displayed);
}
我希望测试的执行方式如下:
安装程序启动浏览器>转到网站>登录
测试顺序1单击报告下拉列表>单击标准报告
测试订单2单击主页按钮>单击报告下拉列表>ProfitAndLoss按钮
实际结果是:
设置-通过,
测试顺序1-通过,
测试顺序2-失败-错误无法找到仅在安装方法期间使用的元素
因此,在玩游戏和谷歌搜索之后,如果我将类的[Setup]方法更改为[OneTimeSetup],那么这将正常工作。新代码如下所示:
[OneTimeSetUp]
public void initalise()
{ //Maximise Window
driver.Manage().Window.Maximize();
//Navigates to the NG Test DB
driver.Url = "https://TESTWEBSITE.co.uk";
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
//Find Company Text Box and send company name
driver.FindElement(By.XPath("//input[@id='txtCompany']")).SendKeys("CompanyName");
//Find username Text Box and send username
driver.FindElement(By.XPath("//input[@id='txtUsername']")).SendKeys("6969_1");
//Find password and send
driver.FindElement(By.XPath("//input[@id='txtPassword']")).SendKeys("Password!");
//Find Login button and click
driver.FindElement(By.XPath("//input[@id='cmdLogin']")).Click();
}
[Test, Order(1)]
public void reportsStandard()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Standard Reports')]")).Click();
IWebElement ReportType = driver.FindElement(By.XPath("//div[@id='ctl00_ContentPlaceHolder_lstReports']//ul[@class='rlbList']"));
//Assert.AreEqual(true, ReportType.Displayed);
}
[Test, Order(2)]
public void reportsPandLCustomer()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[contains(text(),'Home')]")).Click();
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Profit and Loss by Customer')]")).Click();
IWebElement AdvancedFiltering = driver.FindElement(By.XPath("//a[@id='ContentPlaceHolder_cmdAdvancedFiltering']"));
Assert.AreEqual(true, AdvancedFiltering.Displayed);
}
[Test, Order(3)]
public void reportsPandLPhone()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[contains(text(),'Home')]")).Click();
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Profit and Loss by Phone Number')]")).Click();
IWebElement ResetBTN = driver.FindElement(By.XPath("//span[@id='ctl00_FunctionBarPlaceHolder_cmdReset']"));
Assert.AreEqual(true, ResetBTN.Displayed);
}
因此,在玩游戏和谷歌搜索之后,如果我将类的[Setup]方法更改为[OneTimeSetup],那么这将正常工作。新代码如下所示:
[OneTimeSetUp]
public void initalise()
{ //Maximise Window
driver.Manage().Window.Maximize();
//Navigates to the NG Test DB
driver.Url = "https://TESTWEBSITE.co.uk";
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
//Find Company Text Box and send company name
driver.FindElement(By.XPath("//input[@id='txtCompany']")).SendKeys("CompanyName");
//Find username Text Box and send username
driver.FindElement(By.XPath("//input[@id='txtUsername']")).SendKeys("6969_1");
//Find password and send
driver.FindElement(By.XPath("//input[@id='txtPassword']")).SendKeys("Password!");
//Find Login button and click
driver.FindElement(By.XPath("//input[@id='cmdLogin']")).Click();
}
[Test, Order(1)]
public void reportsStandard()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Standard Reports')]")).Click();
IWebElement ReportType = driver.FindElement(By.XPath("//div[@id='ctl00_ContentPlaceHolder_lstReports']//ul[@class='rlbList']"));
//Assert.AreEqual(true, ReportType.Displayed);
}
[Test, Order(2)]
public void reportsPandLCustomer()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[contains(text(),'Home')]")).Click();
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Profit and Loss by Customer')]")).Click();
IWebElement AdvancedFiltering = driver.FindElement(By.XPath("//a[@id='ContentPlaceHolder_cmdAdvancedFiltering']"));
Assert.AreEqual(true, AdvancedFiltering.Displayed);
}
[Test, Order(3)]
public void reportsPandLPhone()
{
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.FindElement(By.XPath("//span[contains(text(),'Home')]")).Click();
driver.FindElement(By.XPath("//span[@class='rpOut']//span[@class='rpText'][contains(text(),'Reports')]")).Click();
driver.FindElement(By.XPath("//span[contains(text(),'Profit and Loss by Phone Number')]")).Click();
IWebElement ResetBTN = driver.FindElement(By.XPath("//span[@id='ctl00_FunctionBarPlaceHolder_cmdReset']"));
Assert.AreEqual(true, ResetBTN.Displayed);
}
标记为[SetUp]的方法在每次测试之前运行,请参阅
我认为问题在于:
安装程序正在运行,请登录
Test1运行,通过测试
由于Test1已完成,安装程序将再次运行,但这一次您已经登录,因为您正在重用浏览器会话,或者至少似乎收到了您发布的代码,因此当安装方法查找Company字段时,它不在那里。
最佳实践是每次测试使用一个浏览器会话。它确保您每次都能进行尽可能干净的跑步。您需要将启动浏览器添加到[SetUp]方法中,并且需要添加退出浏览器的[TearDown]方法。以下是测试的运行方式:
安装程序运行、启动浏览器并登录
Test1运行,通过
“拆卸”运行并关闭浏览器
安装程序运行、启动浏览器并登录
测试2运行,通过
“拆卸”运行并关闭浏览器
您的拆卸方法应该类似于上面链接的文档
[TearDown]
public void Cleanup()
{
driver.Quit();
}
旁注1:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
这实际上并不等待。。。它设置驱动程序实例的等待时间。它只需要设置一次,不应再次使用,除非您想将超时更改为其他值。除了安装方法中应包含的第一个实例外,您可以删除此实例的所有实例
旁注2:
Selenium参与者已声明避免使用ImplicitWait。您应该改为使用WebDriverWait
旁注3:
您的测试不应按特定顺序运行。每个测试都应该相互独立,并且应该能够以任何顺序运行。在每个测试之前运行标有[SetUp]的方法,请参阅
我认为问题在于:
安装程序正在运行,请登录
Test1运行,通过测试
由于Test1已完成,安装程序将再次运行,但这一次您已经登录,因为您正在重用浏览器会话,或者至少似乎收到了您发布的代码,因此当安装方法查找Company字段时,它不在那里。
最佳实践是每次测试使用一个浏览器会话。它确保您每次都能进行尽可能干净的跑步。您需要将启动浏览器添加到[SetUp]方法中,并且需要添加退出浏览器的[TearDown]方法。以下是测试的运行方式:
安装程序运行、启动浏览器并登录
Test1运行,通过
“拆卸”运行并关闭浏览器
安装程序运行、启动浏览器并登录
测试2运行,通过
“拆卸”运行并关闭浏览器
您的拆卸方法应该类似于上面链接的文档
[TearDown]
public void Cleanup()
{
driver.Quit();
}
旁注1:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
这实际上并不等待。。。它设置驱动程序实例的等待时间。它只需要设置一次,不应再次使用,除非您想将超时更改为其他值。除了安装方法中应包含的第一个实例外,您可以删除此实例的所有实例
旁注2:
Selenium参与者已声明避免使用ImplicitWait。您应该改为使用WebDriverWait
旁注3:
您的测试不应按特定顺序运行。每个测试应该相互独立,并且应该能够以任何顺序运行。单击“主页”按钮后。请共享html以查找元素。OP可能会帮助您了解在线ATM。您好,报告的元素保持不变。家b
按钮将用户返回到登录的启动页面。有很多HTML,你有什么特别需要的吗?我认为它无法识别安装程序块中的元素//input[@id='txtCompany']。但是你说安装程序通过了。奇怪!!!我不认为这是问题所在,因为正在发生的是,它正在通过设置块,然后登录。登录后,设置块不应应用,因为登录页面不再存在。然后,它执行测试1,打开通过的reportsStandard,但一旦完成,它将返回到设置块,而不是继续测试Order2 reportsPandLCustomer。由于它正在循环,但没有初始化一个新会话,因此它正在搜索一个txtCompany元素,该元素只会出现在登录页面上。如果我将设置更改为Test,Order1并从那里执行,它确实可以正常工作。因此,测试运行程序返回到安装程序块是一个问题。单击“主页”按钮后。请共享html以查找元素。OP可能会帮助联机ATM的用户。您好,报告的元素保持不变。主页按钮将用户返回到登录的初始页面。有很多HTML,你有什么特别需要的吗?我认为它无法识别安装程序块中的元素//input[@id='txtCompany']。但是你说安装程序通过了。奇怪!!!我不认为这是问题所在,因为正在发生的是,它正在通过设置块,然后登录。登录后,设置块不应应用,因为登录页面不再存在。然后,它执行测试1,打开通过的reportsStandard,但一旦完成,它将返回到设置块,而不是继续测试Order2 reportsPandLCustomer。由于它正在循环,但没有初始化一个新会话,因此它正在搜索一个txtCompany元素,该元素只会出现在登录页面上。如果我将设置更改为Test,Order1并从那里执行,它确实可以正常工作。因此,测试运行程序返回到设置块是一个问题。您不想这样做。这可能会使您当前的代码正常工作,但这不是您测试的结构方式。看看我的答案。谢谢你的帮助杰夫,如果可以的话,继续提问?您提到应该为每个测试启动一个新的浏览器实例,这不会大大增加执行测试所需的时间吗?我不会说太多,但它可能会为每个测试运行增加几秒钟。我们的想法是,通过并行运行它们来补偿这一额外时间,这将大大弥补每次启动浏览器所需的少量额外时间。最后,它对你的帮助大于伤害。。。即使您没有并行运行测试。每次都有一次干净的运行将使您的测试更有弹性,并使调试失败变得更容易。谢谢您的反馈杰夫:您不想这样做。这可能会使您当前的代码正常工作,但这不是您测试的结构方式。看看我的答案。谢谢你的帮助杰夫,如果可以的话,继续提问?您提到应该为每个测试启动一个新的浏览器实例,这不会大大增加执行测试所需的时间吗?我不会说太多,但它可能会为每个测试运行增加几秒钟。我们的想法是,通过并行运行它们来补偿这一额外时间,这将大大弥补每次启动浏览器所需的少量额外时间。最后,它对你的帮助大于伤害。。。即使您没有并行运行测试。每次都有一次干净的运行将使您的测试更具弹性,并使调试失败更容易。感谢您的反馈杰夫:嘿,杰夫,通过在每个类中将[Setup]更改为[OneTimeSetup],这已经解决了问题,我发布了该特定修复作为答案,感谢指向文档的链接,它们会派上用场的!我也有一个拆卸方法,虽然我在代码中没有走那么远,所以没有发布它。我将更改implict wait的实例,我不知道WebDriverWait,因此也非常感谢。关于订单,没有要求他们以这种方式执行,因为除了登录,他们都可以很好地执行,这只是为了便于跟踪,因为我必须在团队中共享这些。嘿,Jeff,通过在每个类中将[Setup]更改为[OneTimeSetup],这解决了问题,我发布了特定的修复作为答案,谢谢你的文档链接,它们会派上用场的!我也有一个拆卸方法,虽然我在代码中没有走那么远,所以没有发布它。我将更改implict wait的实例,我不知道WebDriverWait,因此也非常感谢。关于订单,没有要求他们以这种方式执行,因为除了登录,他们都可以很好地执行,这只是为了便于跟踪,因为我必须在团队中共享这些。