自动测试从设置中列出的代码中抛出错误,尽管它已经在其他测试中正确执行
Automated tests throwing error from code listed in setup despite it having already executed correctly in other tests
我从一组测试中收到一个错误,它似乎正在寻找设置方法中列出的元素,尽管该方法已经被执行,抛出的错误是:
Message: OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":"//input[@id='txtCompany']"}
(Session info: chrome=71.0.3578.98)
(Driver info: chromedriver=2.45.615291
(ec3682e3c9061c10f26ea9e5cdcf3c53f3f74387),platform=Windows NT 10.0.17763 x86_64)"
我已经尝试替换和注释掉代码,我还添加了额外的步骤,即在单击“报告”下拉列表之前返回到初始屏幕,但这并没有解决问题。类似的代码在进行不同测试的 class 之外也能正常工作。
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);
}
我希望测试执行为:
Setup (Launches Browser > Go to Website > Login)
Test Order 1 ( Click Reports Drop Down > Click Standard Report)
Test Order 2 ( Click Home Button > Click Reports Drop Down > ProfitAndLoss Button)
实际结果是:
Setup - Passes,
Test Order 1 - Passes,
Test Order 2 - Fails - Error is unable to locate an element which is only used during Setup Method.
所以在尝试和谷歌搜索之后,如果我将 Class 的 [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]
的方法在每次测试前是运行,见docs。
我认为问题是这样的:
- 设置 运行s,登录
- 测试 1 运行s,通过
- 由于测试 1 已完成,再次设置 运行s 但这次您已经登录,因为您正在重复使用浏览器会话(或者至少看起来已获得您发布的代码)所以当设置方法查找不存在的公司字段。
最佳做法是每次测试使用一个浏览器会话。它确保您每次都能获得最干净的 运行。您需要将启动浏览器添加到您的 [SetUp]
方法中,并且您需要添加一个 [TearDown]
方法来退出浏览器。这就是你的测试应该如何 运行:
- 设置 运行s,启动浏览器并登录
- 测试 1 运行s,通过
- 拆卸 运行s 并关闭浏览器
- 设置 运行s,启动浏览器并登录
- 测试 2 运行s,通过
- 拆卸 运行s 并关闭浏览器
您的 TearDown 方法应该类似于(参见上面链接的文档)
[TearDown]
public void Cleanup()
{
driver.Quit();
}
旁注 1:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
这实际上并没有等待...它设置了 driver
实例的等待时间。它只需要设置一次,除非您想将超时更改为不同的值,否则不应再次使用。除了第一个应该在您的设置方法中的实例之外,您可以删除它的所有实例。
旁注 2:
Selenium 贡献者声明要避免使用 ImplicitWait
。您应该改用 WebDriverWait
.
旁注 3:
您的测试不应按特定顺序 运行。每个测试应该相互独立,并且应该能够 运行 以任何顺序。
我从一组测试中收到一个错误,它似乎正在寻找设置方法中列出的元素,尽管该方法已经被执行,抛出的错误是:
Message: OpenQA.Selenium.NoSuchElementException : no such element: Unable to locate element: {"method":"xpath","selector":"//input[@id='txtCompany']"}
(Session info: chrome=71.0.3578.98)
(Driver info: chromedriver=2.45.615291
(ec3682e3c9061c10f26ea9e5cdcf3c53f3f74387),platform=Windows NT 10.0.17763 x86_64)"
我已经尝试替换和注释掉代码,我还添加了额外的步骤,即在单击“报告”下拉列表之前返回到初始屏幕,但这并没有解决问题。类似的代码在进行不同测试的 class 之外也能正常工作。
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);
}
我希望测试执行为:
Setup (Launches Browser > Go to Website > Login)
Test Order 1 ( Click Reports Drop Down > Click Standard Report)
Test Order 2 ( Click Home Button > Click Reports Drop Down > ProfitAndLoss Button)
实际结果是:
Setup - Passes,
Test Order 1 - Passes,
Test Order 2 - Fails - Error is unable to locate an element which is only used during Setup Method.
所以在尝试和谷歌搜索之后,如果我将 Class 的 [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]
的方法在每次测试前是运行,见docs。
我认为问题是这样的:
- 设置 运行s,登录
- 测试 1 运行s,通过
- 由于测试 1 已完成,再次设置 运行s 但这次您已经登录,因为您正在重复使用浏览器会话(或者至少看起来已获得您发布的代码)所以当设置方法查找不存在的公司字段。
最佳做法是每次测试使用一个浏览器会话。它确保您每次都能获得最干净的 运行。您需要将启动浏览器添加到您的 [SetUp]
方法中,并且您需要添加一个 [TearDown]
方法来退出浏览器。这就是你的测试应该如何 运行:
- 设置 运行s,启动浏览器并登录
- 测试 1 运行s,通过
- 拆卸 运行s 并关闭浏览器
- 设置 运行s,启动浏览器并登录
- 测试 2 运行s,通过
- 拆卸 运行s 并关闭浏览器
您的 TearDown 方法应该类似于(参见上面链接的文档)
[TearDown]
public void Cleanup()
{
driver.Quit();
}
旁注 1:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
这实际上并没有等待...它设置了 driver
实例的等待时间。它只需要设置一次,除非您想将超时更改为不同的值,否则不应再次使用。除了第一个应该在您的设置方法中的实例之外,您可以删除它的所有实例。
旁注 2:
Selenium 贡献者声明要避免使用 ImplicitWait
。您应该改用 WebDriverWait
.
旁注 3: 您的测试不应按特定顺序 运行。每个测试应该相互独立,并且应该能够 运行 以任何顺序。