1
votes

I am a newbie to Selenium and after much research, I have come to a halt. I have seen various examples with code similar to what I have below:

class LoginPage
{
    private IWebDriver driver;

    public LoginPage(IWebDriver driver)
    { this.driver = driver; }

    //HomePage appears when Login successful
    public HomePage DoLogin(string user, string pass)
    {
        driver.FindElement(By.Name("userfield")).SendKeys(user);
        driver.FindElement(By.Name("passfield")).SendKeys(pass).Submit();

        //what is the above fails and i stay on the LoginPage? returning a HomePage object will be a bad idea here

        HomePage homepage = new HomePage(driver)
        PageFactory.InitElements(driver, homepage)
        return homepage;
    }
}

class HomePage{
    public HomePage(WebDriver driver)
    { this.driver = driver; }

    public void clickExitButton() 
    {
        exitButton.click();
    }

    public LoginPage logout() 
    {
        clickExitButton();

        LoginPage loginpage = new LoginPage(driver)
        PageFactory.InitElements(driver, loginpage);
        return loginpage;
    }
}

My question:

  1. What is either of the classes fail to do what they are supposed to do? What if Login fails? It will still return HomePage object. This should not be the case, right? What can be done to tackle a fail? Most of the examples I have seen assume that things "will" work out correctly.

  2. Is the above implementation correct for C#? Most of the examples I have seen are for Java - just wanted to convert them to C# as I know C# :)

Thanks!

2

2 Answers

1
votes

For your first question, the way I have addressed it before is to include a function in each page class that indicates whether Selenium is currently on the page expected. For example, the Homepage class would have something like:

public bool IsCurrentPage()
{
    try
    {
        driver.FindElement(By.LinkText("Logout"));
    }
    catch (Exception)
    {
        return false;
    }
    return true;
}

So when you create a new Homepage, you immediately check that it is valid:

HomePage homepage = new HomePage(driver);
if (!homepage.IsCurrentPage())
   throw new Exception("Invalid homepage object");

You are then free to handle the mismatch in whatever way is appropriate for your purposes. Of course the method can be fooled, so another option is to check the URL for a page name (homepage.html for example). How strict you are on your page checks is up to you depending on how much accuracy and flexibility you want.

For your second question, aside from a couple missing semicolons the code looks fine.

0
votes

For your first question: Selenium will not return a Homepage object if it fails to find either the "userfield" or "passfield".

By using the FindElementBy(...) methods you are implicitly making an assumption that those fields must be there. If Selenium does not find the "userfield" or "passfield" elements on the page, it will throw an exception. Effectively "failing" the test right there.

Typically, the way this process works is that nUnit will kick off the Integration test. If Selenium does not find one of the elements that are required for continuing then that specific Integration test will fail.

In my opinion, this is why it is beneficial to keep your integration tests as compartmentalized as possible. Ensuring that there is not too much setup work involved in testing the behavior that you want to ensure is working.

I've also found this extension method very useful for ensuring specific elements are not on the page. Keep in mind this extension method falls prey to the Selenium "ImplicitWait" time. This one call will effectively require that N seconds pass before moving on.

public static class RemoteWebDriverExtensions
{
    public static bool ElementDoesNotExist(this RemoteWebDriver driver, By by)
    {
        try
        {
            var element = driver.FindElement(by);

            return false;
        }
        catch (Exception)
        {
            return true;
        }
    }
}

which can ultimately be used as such:

driver.ElementDoesNotExist(By.LinkText("Logout"));