Awesome Page Objects In Testing

I mentioned page objects in the post about WatirSplash 2. In this post i’m gonna explain what these things exactly are and how to use them.

What Is A Page?

When it comes to automated testing then the page is really nothing else than the page user sees when visiting the website. Any meaningful page consists of different components some of which just show information (e.g. text) others allow interaction (e.g. text fields and buttons). Different pages might also have some shared content like header, search field and footer. One important thing about components is that the result of some interactions is another page.

Let me bring you a concrete example. Let’s look at the Bing’s main page (enough of Google in all examples, alright). You can think of the possible sections (Web, Images, Videos, News and More) as a header. There is also the search field and button. Search button is special since clicking on it changes the current page to results page. Makes sense? Let’s see how to convert that information into WatirSplash Page Objects.

Point Of Having Page Objects

The point of having Page Objects is to have better structured code and keep it DRY in your tests too. This all makes your tests easier to maintain. If you’re a software developer then you care about these things when it comes to production code. Why not to use these good practices in tests also? Page Objects make it all possible. Having Page Objects means that it should be easier to change your tests if the application under test (AUT) changes since you need only one place (ideally) to change. Page Objects also make it very clear where to find existing and put the new code.

Let’s Get Rockin’ With Pages And Objects

Let’s get more concrete. I assume that you have created a WatirSplash 2 project already. If not then follow the instructions in the post about WatirSplash 2 or read everything you need to know straight from the README. Let’s create the Main page first:

This command created us the Main page object and a test for it. The generated file looks like this:

And the test itself is nothing fancy yet:

Let’s add something meaningful to our Main page object like search field and button:

You can use all the familiar Watir methods directly in your Page objects! For the sake of clarity let’s also add Header functionality. To do that we’d just use Ruby’s mixin functionality - the Header module:

And make sure to include it into your page object:

We can now update our main_spec to actually test something:

I made two tests - one for the header and another for the search functionality. Since header should be on every page, i could have taken advantage of the RSpec’s Shared Examples feature, but for the sake of this post’s clarity i didn’t.

The second test is a failing test since there’s no way that Watir’s Button#click will return us a results page object. But hey, i’ve just done a little TDD here! Let’s make it work like we want it to work:

I’ve used the WatirSplash::Page::Base#modify method which takes some object as it’s first argument (here button) and a Hash as a second argument. Hash consists of method name as a key and value as Proc object. In this particular case the code above overrides this particular button’s #click method with my #click, which returns Results page object due to the usage of #redirect_to method. Since #click is already existing method on that button, then it will call the original method (e.g. performs the actual clicking) before calling the defined block. The #modify method does all that by using Ruby’s meta-programming. You can always look at the source itself if you’re more interested in the nitty-gritty details.

Let’s create ourselves a Results page object with the results method. This time, let’s be even cooler and generate more code than we did with the Main page object:

This generated us the Results class with the results method:

Let’s add the #count and #[] methods to our #results object by using #modify again so we could chain method invocations naturally as i’ve written in the search functionality test:

I’m invoking the #results method again to get the Watir::Ul element to execute regular Watir methods on it - in these cases #li and #lis. This neat trick hides the implementation details from the tests and makes the tests even more natural to read.

In Conclusion

That’s it - we have created a few tests using Page Objects functionality in WatirSplash 2! Using Page Objects makes your tests (hopefully) more readable and easier to maintain. I like my implementation when compared to others because it makes your page objects to look really succinct and doesn’t add any additional complex API to learn - you can use already learnt Watir methods as you did before. And the code written to support creating and using these Page Objects is also quite clever and short. I love it! I hope you will too.

Facebook, Watir And Testing

I’ve known some time now that Facebook has been using Watir as their integration testing tool. Hell, there’s even a Facebook logo on the main page of watir.com. But today was a special day because i had to read one article about Facebook moving away from Watir.

Confusions

Since i’m one of the few core developers of Watir then this article made me notice statements which are not true or are just misleading. It seems to me that the author of that post doesn’t know the insights of Watir and other tools he’s mentioning or just uses wrong terminology by accident.

Watir & JavaScript

First statement which forced me to questioning myself was the following: “Watir automates the browser with JavaScript…”.

It took me some time before i understood that the author had FireWatir in his mind and not the Watir itself. FireWatir was used to automate Firefox browser and it truly used JavaScript as it’s engine to perform all the automations. Watir on the other hand controls Internet Explorer and uses it’s OLE interface instead to control the browser. This means in effect that there’s almost no JavaScript used in Watir.

Watir != Watir-WebDriver != WebDriver

The next statement causing confusion is: “The Watir we adopted in 2009 has since been improved, integrating a new protocol called WebDriver which allows you to automate the browser more accurately and with more power than could previously be done with straight JavaScript.”

First - Watir has been improved indeed when compared to year 2009 :) This is a good thing and a true statement. Second - Watir doesn’t integrate with the new protocol called WebDriver - it does still use OLE. I’m not exactly sure what the author means by the end of his statement about more accuracy and power. And of course - third - as mentioned already, Watir itself doesn’t use JavaScript and didn’t even do that in the year of 2009.

I think that you can call the WebDriver as a protocol, but the most famous implementation of that protocol is for sure Selenium-WebDriver aka Selenium 2. Watir-WebDriver is a library written on top of Selenium-WebDriver’s Ruby bindings. In other words it is an improved API over Selenium’s API. At least this is the way, we, Watir-loving people like to think. It does even have some API improvements which vanilla Watir doesn’t have yet. There is a project called WatirSpec, which is the specification for Watir’s API. Even Watir itself doesn’t conform to that yet. But the ultimate goal is to make Watir-WebDriver and Watir 100% compatible with each other. Latest releases of Watir have been moving towards that goal.

Abandoning Watir

And then i have to read the saddest statement of that article: “Once I understood all these factors, my course of action seemed clear: Abandon Watir, create a WebDriver client in PHP, and reuse our mature PHP unit test system for our browser tests. The WebDriver protocol was straightforward enough that I had a fully featured client in PHP by the end of a weekend’s work.”

On the one hand i’m happy that the engineers in the Facebook try to make things better - having the same technologies used between different projects is always a good thing. On the other hand i’m not sure i understand as to why they had to create a new PHP WebDriver bindings. Looking from the main page of Selenium 2 i can see that there’s already two seemingly active projects doing just that - php-webdriver-bindings and WebDriver-PHP. Maybe engineers at Facebook had good reasons why not to use something already existing. Maybe they just like to feel more challenged and want to invent few bicycles in a while. I don’t know.

Conclusion

After all it was an interesting read. Since i’ve used Watir about 4 years now then it’s nice to read that someone else had similar or completely different solutions to the same problems. I like the thing about Facebook that it tries to be more open to the world when it comes to the topics of the tools and processes used to make, maintain and release such a widely used product.

On the other hand, posts having false information in them tend to have a strong effect on people using the tools under fire. Especially if this kind of information is originating from a trustworthy source. From that post it seems that it is time to abandon Watir since it is too old and not developed anymore. That’s just plain wrong. Watir is still actively developed and one of the biggest reasons why not to abandon Watir at this moment is that it is still the best automation tool for Internet Explorer. Watir-WebDriver’s IE driver is just not mature enough. Sorry, WebDriver guys. I would be happy to run all my tests with Watir-WebDriver since that would give me an opportunity to test with different browsers, but as long as IE is not working properly, then i just can’t do that. Since IE is the brittlest and still most used browser, then testing with that browser just seems to be mandatory.

I have to agree that if the person is not tied with all or some of these projects on a daily basis then it is hard to understand the difference between Watir, Watir-WebDriver and WebDriver. Maybe the biggest problem is just that the topics aren’t documented enough?

Fighting Against Gem Hell

There is a term called DLL Hell which in my opinion exists also in the Ruby community with the different name - Gem Hell. This potential problem exists when dependencies for your project and/or libraries are not managed properly.

I’ve written in the post WatirSplash 2 about loading all the dependencies with the help of the Bundler, which helps to organize the dependencies in a sanely way and tries to eliminate the Gem Hell problem. In this post i’m gonna give a more detailed overview of how the things were before and how they are now in the WatirSplash framework.

Story Behind WatirSplash’ Dependencies

Since WatirSplash is a framework which supports using different frameworks for browser automation (Watir, Watir-WebDriver and FireWatir) then there needs to be some kind of a mechanism for defining the install and runtime dependencies. Install dependencies are easy to specify since they can be put right into the .gemspec file of the WatirSplash gem and RubyGems does all the heavylifting:

It gets trickier when it comes to specifying the runtime dependencies. “Why runtime dependencies at all?” - you might ask. The answer to this question is fairly simple - because the framework used for automating the browser is chosen during runtime and it’s not possible to put all these gems into installation dependencies due to the problem of Watir (for controlling the IE browser) not installing successfully on Linux or OS X operating systems for obvious reasons. There are also other OS-specific gems. Also, it’s not possible (at least not in my knowledge of) to specify platform specific dependencies right into the .gemspec file itself.

The Old Way

The runtime dependencies in WatirSplash 1 were loaded with the help of the RubyGems itself. When the desired framework was specified then WatirSplash loaded the appropriate file, which executed the code similar to this for Watir:

It meant that the user of WatirSplash needed to have the Watir version 2.0.1 installed and if he didn’t then the installation instructions were provided.

This solution seems to solve the problem of specifying runtime dependencies at first. There are still some problems with this approach. First of all, if Watir has a dependency for some other gem without any specific or with too loose version then it is possible that some newer version of that gem breaks the usage of WatirSplash and i, as a maintainer of the WatirSplash gem, have to release a new version of the WatirSplash gem by specifying the exact version of that gem as a runtime dependency. Second problem is that if a newer version of Watir (or any other among the runtime dependency gems) were released then it was not possible for the user of WatirSplash to try if it was working with the current version of WatirSplash (which was pretty often the case) without modifying the code of WatirSplash itself or waiting for the new release made by me with updated runtime dependencies. These are the two main and quite big problems with this approach.

The New Way

These problems were solved by introducing the usage of Bundler. Bundler allows to specify runtime dependencies exactly like with RubyGems, but it has a difference of locking down the dependencies versions. This means that user A and user B are always using the same versions of all the runtime dependencies no matter what other versions they have installed on their system.

By using WatirSplash 2, you will get the following Gemfile into your specs directory, when running new project generator, for specifying all the needed dependencies:

After executing `bundle install` do not forget to add Gemfile.lock also into your VCS - this is the only way to guarantee that everyone who is running the tests are using the exact same versions of the dependencies.

This solution allows each user of the WatirSplash to specify their own dependency versions without any need to wait for the new release of the WatirSplash itself. In other words - this solution solves both of the problems existent in the previous RubyGems solution.

Conclusion

Bundler tries to make the Gem Hell problem disappear and is doing a pretty good job there, but if there are gems which depend on some external native library, which needs compilation then there is still the danger of having a wrong version of that dependency causing compilation errors. Probability of seeing that problem is quite low compared to the problems which Bundler solves. All in all Bundler is a really great tool and thanks to that WatirSplash has gotten even better.

WatirSplash 2

WatirSplash 2 has been released already some time ago, but i haven’t covered the nice things which came with it. This situation will be improved with the following posts.

New Features

The biggest changes in WatirSplash 2 compared to version 1.x are:

Removed Features

It is quite easy to understand from the “New Features” list that projects generated with WatirSplash 1.x won’t work out of the box with WatirSplash 2. I had to break backwards compatibility due to the decisions made in the past which were in my way improving the framework to make it just a lot better.

I’ve paid attention to the users of WatirSplash and noticed what they didn’t like or what they have been wanting to do differently. This has caused me to use .rspec file to configure RSpec all the way instead of doing it programmatically from the WatirSplash itself. This gives a better control for tuning the usage of RSpec when needed.

Even browser window won’t be opened and maximized automatically anymore - you can still do it with the help of RSpec.configure block.

All these little details should make the experience of using WatirSplash even better!

Getting Started

Starting to use WatirSplash is as easy as splashin’ in the water. First you have to install the gem itself ofcourse:

After doing that you’d need to generate a default project structure. It can be done by using the “new” generator:

Being inside of the newly created project directory, install all the required dependencies aswell:

After having that done, generate the very first Page Object with the “page” generator. For example:

There you have it. Modify the newly generated files and start specc’ing. There will be a more thorough posts about the main new features including how to use Page Objects in the future - stay tuned. Feel free to read more information about WatirSplash from it’s repository at GitHub.

WatirSplash With Different Browsers

WatirSplash supported only Windows operating system and IE browser to perform browser based user interface testing. The reason behind that restriction was the usage of Watir framework, which by design is Windows-specific and controls Internet Explorer. Using that browser to test is usually great because most of the developers (including myself) are not using IE during their development time and it is also the most error-prone browser. This all means that it’s good to run your tests with the IE since it has the highest probability to find some bugs during the creation of the tests and in the future.

Gimme More!

Starting from WatirSplash version 1.1.0 it is now possible to run tests in Linux and OS X by using Firefox and Chrome browsers. This functionality is provided by using other frameworks in addition to Watir itself - FireWatir and Watir-WebDriver. WatirSplash allows easy switching between the frameworks and browsers.

Switching the Frameworks

It is possible to switch the framework by using environment variable or by just specifying the framework in the code.

All possible values for different frameworks and browsers are currently the following:

  • watir
  • firewatir
  • watir-webdriver/ie
  • watir-webdriver/firefox
  • watir-webdriver/chrome

Use environment variable called WATIRSPLASH_FRAMEWORK to specify the current framework:

This makes your WatirSplash project tests to use Watir-WebDriver framework with Firefox browser. Pretty straight-forward.

As written above then it is also possible to specify the used framework directly in the code. It is meant to be done in your config.rb file under the ui-test and/or ui-test-common directories. If you specify it in the ui-test-common directory then the ui-test directory has higher precedence and framework specified there will be used. On the other hand if you don’t have any frameworks specified in the ui-test directory then the framework specified in the ui-test-common directory will be used. The framework to be used can be specified like this:

This statement makes WatirSplash to use FireWatir framework with Firefox browser (obviously).

Framework specified by environment variable has always the highest precedence, then comes the ui-test’s and ui-test-common’s config.rb, in that order.

Default Frameworks

This additional functionality in WatirSplash is fully backwards compatible. If the framework is not specified anywhere then the default framework will be used. The default framework depends of the platform where the tests are ran. The default framework in Windows is Watir and in Linux/OS X it is FireWatir.

Possible Dangers

You have to keep in mind that switching the frameworks could cause some problems when running the tests due to the different incompatibilities between the frameworks. Watir and FireWatir, for example, are not 100% compatible with each other. Same goes for Watir and Watir-WebDriver. Also, i’d not consider Watir-WebDriver’s IE and Chrome drivers stable yet. The only driver i’d recommend to use from Watir-WebDriver would be Firefox’s.

Conclusion

There you have it - a quite flexible solution for all your browser testing needs. Just have some things in your mind while switching the frameworks and you’re good to go. There will be probably more supported frameworks added to WatirSplash in the future. Just keep an eye on the changelog.