简体   繁体   中英

Specflow NoSuchElementException Could not find element by By.XPath

I have rearranged my class files and Webdriver variable so I can use Context Injection to share the Webdriver variable between steps. Before I was using SetupFixture, Setup and TearDown which is not correct for BDD. Trying Context Injection now with BeforeAllTests, BeforeTestRun etc. My FindElement using XPATH is not working. It used to work before I started to rearrange my class files.
I am getting the error:

OpenQA.Selenium.NoSuchElementException : Could not find element by: By.XPath: .//*[@id='twotabsearchtextbox']

The line highlighted where the error is here:

Searchfield_XPATH.SendKeys(text);

The XPath locator is defined as :

[FindsBy(How = How.XPath, Using = ".//*[@id='twotabsearchtextbox']")]
private IWebElement Searchfield_XPATH { get; set; }

My code snippet is as follows:

//class setup.cs:
namespace SearchTest.Setup
{
    [Binding]
    public class BeforeAllTests
    {
        private readonly IObjectContainer objectContainer;
        private static SeleniumContext seleniumContext;

        public BeforeAllTests(IObjectContainer container)
        {
            this.objectContainer = container;
        }

        [BeforeTestRun]
        public static void RunBeforeAllTests()
        {
            seleniumContext = new SeleniumContext();
            seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
        }

        [BeforeScenario]
        public void RunBeforeScenario()
        {
            objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
        }
    }
}

// Class SeleniumContext.cs
namespace SearchTest.WebDriver
{
    public class SeleniumContext
    {
        public IWebDriver driver { get; private set; } 

        public SeleniumContext() 
        { 
            //create the selenium context
            driver = new FirefoxDriver();
     }
    }
}

//Class HomePage.cs
namespace SearchTest.PageObjects
{
    [Binding]
    public class HomePage : PageObjectBase 
    {
        private SeleniumContext seleniumContext;
        //private IWebDriver driver{ get; set; }

        [FindsBy(How = How.XPath, Using = ".//TITLE")]
        public IWebElement Title{ get; set; }

        // search text field on the homepage
        //[FindsBy(How= How.Id, Using="twotabsearchtextbox")]
        //private IWebElement Searchfield_ID { get; set; }

        [FindsBy(How = How.XPath, Using = ".//*[@id='twotabsearchtextbox']")]
        private IWebElement Searchfield_XPATH { get; set; }

        [FindsBy(How = How.Id, Using = "nav-search-submit-text")]
        private IWebElement SearchButton { get; set; }

        [FindsBy(How = How.XPath, Using = ".//*[@id='nav-search']/form/div[2]/div/input")]
        private IWebElement searchButton_Xpath {get; set;}

//        public HomePage(IWebDriver driver)
        public HomePage(SeleniumContext seleniumContext) : base(seleniumContext)
        {
            //driver1 = new FirefoxDriver();
           //Console.Out.WriteLine(driver1.Title);
            //driver1.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5)); // Set implicit wait timeouts to 5 secs
            //PageFactory.InitElements(driver1, this);
            this.seleniumContext = seleniumContext;
            PageFactory.InitElements(seleniumContext.driver, this);
        }

    public void goToURL() {
        //driver = new FirefoxDriver();
        //driver1.Navigate().GoToUrl("http://localhost:8080");
    }

    public void EnterSearchText(String text)
        {
            Searchfield_XPATH.SendKeys(text);
        }

    public SearchResultsPage click_search_button() {
        searchButton_Xpath.Click();
        return new SearchResultsPage(seleniumContext);
    }

    }   
}

//Class PageObjectBase.cs
namespace SearchTest.PageObjects
{
    public class PageObjectBase
    {
        private SeleniumContext seleniumContext;
        //private IWebDriver Driver { get; set; }

        public PageObjectBase(SeleniumContext seleniumContext)
        {
            this.seleniumContext = seleniumContext;
            //Driver = driver;
            //Driver = new FirefoxDriver();
            //Console.Out.WriteLine("From base class Driver.title = " + Driver.Title);
            //if (Driver.Title != titleOfPage)
            //    throw new NoSuchWindowException("PageObjectBase: The Page Title doesnt match.");
        }
    }
}

//The HTML is:

<form class="nav-searchbar" role="search" name="site-search" method="GET" action="/s/ref=nb_sb_noss" accept-charset="utf-8">
    <div class="nav-left">
    <div class="nav-right">
    <div class="nav-fill">
    <div class="nav-search-field">
        <input id="twotabsearchtextbox" class="nav-input" type="text" tabindex="21" autocomplete="off" name="field-keywords" value=""/>
    </div>
    <div id="nav-iss-attach"/>
</div>
</form>

How can i resolve this? I am new to BDD, if you see anything wrong with my setup and want to suggest how I can improve it please do.

Since adding the following bit of code:

[BeforeScenario]
    public void RunBeforeScenario()
    {
        objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
        // HERE INSTEAD
        seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
    }

The error I am getting is:

System.ArguementNullException: Value cannot be Null. 

The line highlighted is here: objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);

My code is:

public class BeforeAllTests
{
    private readonly IObjectContainer objectContainer;
    private static SeleniumContext seleniumContext;

    public BeforeAllTests(IObjectContainer container)
    {
        this.objectContainer = container;
    }

    //[BeforeTestRun]
   // public static void RunBeforeAllTests()
   // {
   //     seleniumContext = new SeleniumContext();
   //     seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
   // }

    //[BeforeScenario]
    //public void RunBeforeScenario()
   // {
   //     objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
   //}

    [BeforeScenario]
    public void RunBeforeScenario()
    {
        objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
        // HERE INSTEAD
        seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
    }
}

}

I would guess that you do not want the line

seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");

in your method tagged [BeforeTestRun] , as this then just navigates only once to that URL, before ALL of the tests are run (not before each one).

It may make more sense to have it in the method tagged [BeforeScenario] , as this will then navigate you to your base URL before each scenario executes. This is more likely what should occur, as scenarios should not depend on each other (so, one scenario shouldn't depend on another one having navigated to a particular page).

[BeforeScenario]
public void RunBeforeScenario()
{
    objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
    // HERE INSTEAD
    seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
}

This could explain why Selenium is failing to find that particular element, as it may not actually be on the correct page when the step definition is run.

EDIT:

So the final code for BeforeAllTests would be:

public class BeforeAllTests
{
    private readonly IObjectContainer objectContainer;
    private static SeleniumContext seleniumContext;

    public BeforeAllTests(IObjectContainer container)
    {
        this.objectContainer = container;
    }

    [BeforeTestRun]
    public static void RunBeforeAllTests()
    {
        seleniumContext = new SeleniumContext();
    }

    [BeforeScenario]
    public void RunBeforeScenario()
    {
        objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
        seleniumContext.driver.Navigate().GoToUrl("http://localhost:8080");
    }
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM