This is the third post in a series on creating automated UI tests for an ASP.NET app using C# and Selenium. My goal is to highlight and explain the key pieces required starting with Selenium WebDriver in 2017.
Last post I took a bit of a tangent from WebDriver and instead looked at starting the application automatically when tests are run. This time I have added some more realistic UI tests on a mock login page in the web app in the SeleniumExamples repo. To reduce code duplication and make the tests less brittle I have used the page object pattern, and to wait for the login request/response I used the WebDriverWait class.
Up until now I have not required the Selenium.Support nuget, but this week I have added it in as it provides classes for waiting and creating page objects.
Page objects are not specific to Selenium, but are a pattern for decoupling the logic for interacting with a UI element from your tests. This reduces the brittleness of UI tests, making updating your tests for UI changes quicker.
In the PageObjects namespace in Selenium.Support there are classes to help simplify page object creation. Unfortunately there does not seem to be a lot information on them (the page in the Selenium wiki is not relevant for .NET). I found the best place to learn and get some examples were the test classes in the Selenium source code, but hopefully the page object class for the login page is a better example.
When UI testing with Selenium there will be times when you need to wait for things such as responses to requests or animations to complete. A basic, but inefficient, approach would be to use Task.Delay (or an equivalent) to cause the test to wait. WebDriver provides a better approach for waiting where you set a max timeout and it polls the condition until it is reached, or the time expires.
For .NET there are 2 types of waits available in WebDriver – implicit and explicit. You may see another type, fluent waits, mentioned around the internet, but this is not available in .NET. As far as I can tell fluent waits behave the same as explicit waits, but are declared in a fluent manner.
The Selenium docs provide some details on implicit and explicit waits, but I found this answer on StackOverflow a better source of information. To summarise implicit waits are a one size fits all solution that only applies to finding elements, while explicit waits provide more flexibility and allow waiting for any condition to be met. As the official documentation mentions, implicit and explicit waits should not be mixed as they can cause unreliable wait times.
I used explicit waiting in the login page object to wait for the simulated login request/response to complete. I haven’t tried, but using implicit waits with the page object pattern seems like it would be difficult and I think having the explicit waits in the code to document where there is expected to be a delay is beneficial.
That’s it for this week. From here the plan is to go and create some tests and then look at libraries like Seleno to see how they make it easier.