I am receiving a error from a group of tests where it seems to be looking for an element listed in the Setup Method despite the method already being executed, the error being thrown is:
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)"
I have tried replacing and commenting out code, I have also added in the extra step of returning to the Splash screen before clicking on the Reports drop down though this has not fixed the problem. Similar code works correctly outside of this class where a different test is taking place.
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);
}
I would expect that the Tests execute as:
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)
The actual result is:
Setup - Passes,
Test Order 1 - Passes,
Test Order 2 - Fails - Error is unable to locate an element which is only used during Setup Method.
So after playing around and some googling If I change the [Setup] Method to [OneTimeSetup] for the Class Then this works correctly. New Code will look like:
[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);
}
The method tagged with [SetUp]
is run before each test, see docs .
I think the problem is this:
Best practice is to use one browser session per test. It ensures that you have the cleanest run possible each time. You need to add launching the browser to your [SetUp]
method and you need to add a [TearDown]
method that quits the browser. This is how your tests should run:
Your TearDown method should be something like (see the docs linked above)
[TearDown]
public void Cleanup()
{
driver.Quit();
}
Side note 1:
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
This does not actually wait... it sets the wait time for the driver
instance. It only needs to be set once ever and shouldn't be used again unless you want to change the timeout to a different value. You can remove all the instances of this except for the first one that should be in your Setup method.
Side note 2: Selenium contributors have stated to avoid using ImplicitWait
. You should instead use WebDriverWait
.
Side note 3: Your tests should not be run in a particular order. Each test should be independent of each other and should be able to run in any order.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.