自动测试从设置中列出的代码中抛出错误,尽管它已经在其他测试中正确执行

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

我认为问题是这样的:

  1. 设置 运行s,登录
  2. 测试 1 运行s,通过
  3. 由于测试 1 已完成,再次设置 运行s 但这次您已经登录,因为您正在重复使用浏览器会话(或者至少看起来已获得您发布的代码)所以当设置方法查找不存在的公司字段。

最佳做法是每次测试使用一个浏览器会话。它确保您每次都能获得最干净的 运行。您需要将启动浏览器添加到您的 [SetUp] 方法中,并且您需要添加一个 [TearDown] 方法来退出浏览器。这就是你的测试应该如何 运行:

  1. 设置 运行s,启动浏览器并登录
  2. 测试 1 运行s,通过
  3. 拆卸 运行s 并关闭浏览器
  4. 设置 运行s,启动浏览器并登录
  5. 测试 2 运行s,通过
  6. 拆卸 运行s 并关闭浏览器

您的 TearDown 方法应该类似于(参见上面链接的文档)

[TearDown]
public void Cleanup()
{
    driver.Quit();
}

旁注 1:

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

这实际上并没有等待...它设置了 driver 实例的等待时间。它只需要设置一次,除非您想将超时更改为不同的值,否则不应再次使用。除了第一个应该在您的设置方法中的实例之外,您可以删除它的所有实例。

旁注 2: Selenium 贡献者声明要避免使用 ImplicitWait。您应该改用 WebDriverWait.

旁注 3: 您的测试不应按特定顺序 运行。每个测试应该相互独立,并且应该能够 运行 以任何顺序。