I want to share my approach to making your page object methods a bit more "less flaky" but also easier to maintain and more flexible. Am not going to try and cover everything in one post, so here is the first.
Populating a field on a page.
Excellent, we all know how to do this.
So if we run this, unless we get an exception, we just expect the username field is now populated.
Well lets change it to a bool so our tests have something to assert against.
So now, we can assert this method returns true, and just let an exception inform us that it has failed.
Still not great, we are either going to get true or exception, so lets add a try/catch so we can catch exceptions and return false.
So now we would be able to use this method for positive and negative testing, if we were expecting an exception, our test would be asserting a false response.
But what about the different exceptions we could receive, if we are always returning false, we don't know what caused it, so for a start we could output this to the console, this introduces a manual task, however I will post about more complex approaches in different post.
So making it a bit more robust, we know we have to interact with an element, so why don't we wait for that element first, if its there, we carry on if not lets wait a bit.
So we have introduced a few new things in this code snippet, firstly I have included my locators dictionary, this approach can be found here. Secondly, I have included a WebDriverWait object, this can be found in the "OpenQA.Selenium.Support.UI" name space.
I have added the time to wait as a parameter to the method, I do this as sometimes you might be testing the speed of the application, other times you may want to use the global timeout, this gives you that flexibility. Also added an error message for when this wait expires, providing specific error to reduce investigation time upon a failure.
So we now wait, and can catch if there is a problem, but we can do more.
Lets check that the element is enabled, you might say, why wouldn't it be, who knows, but by doing this we can provide a specific message again reducing investigation time.
Ok, so we are getting there, but how do we know the field is now populated with what we asked WebDriver to populate it with, we don't, so lets check that as well.
You will see that I have also added to clear the field before populating it, not everyone will want this, but it something to consider, depending on your applications behaviour. You could have a method to clear it first.
So as you can see there are several things we do to reduce flakiness, and also reduce investigation time.
So I also said maintenance, well obviously we aren't going to write all this everytime we want to populated a field, so we extract this to a library or I have added this to my default page object as a protected method, a few tweaks and we end up with this:
We can than call this method from our page objects, as all with have access to it, as they all inherit from DefaultPage.
As mentioned, there is better approach to handling exception, but hopefully you get an idea of what else you can do to reduce flakiness in some of your methods, but also reduce investigation time with failures, with smarter reporting.
I have deliberately called this post Paper vs, Steel, paper was just chosen as I was trying to thing of something weak, and there is always a pile of it on my desk, as its my favourite testing tool,
Then Steel, its a very strong material, but not the strongest, so while I think my approach is strong, I know its not the best, so if you can see a way I can improve it, then let me know, and perhaps future posts can be about titanium methods!