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.
This post is inspired by one of the over-3-year-old-posts about using Autotest with Growl to show nice notifications about passing and failing tests.
Doom-Guy is here!
I’ve created a small gem for you to get the same helper for your testing needs. It is called autotest-doom which works with RSpec. Read below for installation and configuration instructions.
This is how it looks under Windows when everything is green and Doom-Guy is happy:
He looks a little bit hesitant, if something has failed:
It looks like his day has gotten even worse:
I’d say that there is definitely some visible blood when you’re having this many failures:
You’d better get yourself together and fix those failing tests now or he’s going to die!
And he’s dead… Do you really want to be such a lousy software developer?
Maybe, just maybe, if you’ll fix all the tests he will be alive again and you’ll be a lifesaver. Wouldn’t that just feel awesome?
Installation & Configuration
In today’s Ruby world things are a little different compared with the previously mentioned old post. My approach is to support not just OS X, but also Windows and Linux. It is possible via help of Test Notifier gem, which has created a clean API by using abstraction layer for using different tools to show notifications. It uses Growl under OS X, Libnotify among many others under Linux and Snarl under Windows.
The following instructions are for Windows, but they’re really similar to other OS-es too. Just refer to Notifier’s documentation about installing correct notifier tool for your OS and you’re ready to go.
Win32-Screenshot is a library in Ruby for capturing screenshots on the Windows operating system. In this post i’m gonna write about the history of this gem since it just made it to the version 1.0.0 and i find that it deserves some extra attention due to the changes it has gone through.
Pre-Historic Times
The gem was originally created by Aslak Hellesøy, now a lead developer of the popular BDD library called Cucumber. Let’s see when was the first commit made to the Win32-Screenshot project by him:
It’s over 4 years old! Deciding of the commit message “Importing”, i’d say that the project started even sooner and got imported to the Git versioning system like this. Too bad that git-svn or something similar was not used to prevent losing the earlier history. The version of the library was at the time 0.0.1. Rails was already rocking with the version of 1.1.6.
Final Publicity
When browsing Git history it’s possible to determine that version 0.0.2 got ready at the 2nd Dec of 2006 and ended up also as a gem on RubyGems. The API was quite simplistic, but also limited:
There was only three simple methods part of the public API - #foreground, #desktop and #window. All of them returned an array of three elements - width, height and bmp. First two represented obviously width and height of the taken screenshot. Last one, bmp, was a blob of the bitmap in string format, which allowed it to be written into file by using Ruby’s File class like demonstrated above.
Inconveniencies
If we’re to think about the problems of that version’s API, then the main one for me was that three-element array returned from the methods. I wanted to use mostly one of the returned variables and it was obviously the one representing bitmap blob. So i had to do something like this:
I didn’t like any of the tricks above. Ruby is meant to be beautiful and this was just not it.
Usability Limitations
The limitations of the API might have not been so obvious, but i’m sure that eventually anyone who was using it, stumbled onto them. There was nothing wrong with the methods #foreground and #desktop since they did what you’d like them to do and there was no way that you’d like them to do anything else (well, maybe you’d have liked the #desktop to take a screenshot of the actual Windows Desktop and not from the entire visible screen, but that is just the functionality of the Windows API itself).
The #window method on the other hand supported only searching Windows with a regular expression so if you wanted to take a screenshot of some window with an exact title you had to use something like /^exact title$/. And you couldn’t do much if you had multiple windows with the exact same title since it was the only thing by which you could search by. Maybe you got lucky and got the correct window each time. Maybe you didn’t.
There were an internal methods called #get_hwnd and #capture_hwnd which allowed you to get the handle of the window and take a screenshot of it. The only problem was that #get_hwnd allowed to search for windows only by the regular expression of the title like #window did. If you got the handle to your window from somewhere else then you didn’t have any problems of capturing the correct window. Lucky you.
Technical Limitations
The main technical limitation of the Win32-Screenshot 0.0.2 was that it was using Windows API via Ruby/DL. The problem with that is the fact that DL is part of the Ruby standard libraries and isn’t compatible between different Ruby versions which automatically meant that Win32-Screenshot was not usable between different versions of Ruby either. There were also occasional segmentation faults happening caused by the DL.
Other big technical limitation was the need to use the RMagick gem to save screenshots into some other formats than big file-sized bitmap (bmp). If you’ve used RMagick on Windows then you ought to know that the installation of it can be quite painful.
Allow me to fill you in with the details in case you’re not aware of the complexity of that procedure. You have to install ImageMagick. And not any version will do, but you have to install very specific version of ImageMagick to make your experience a little more pleasant. You can get the specific version from the RMagick website. The provided 24 MB compressed file includes also the gem for that specific version which you can install with usual `gem install` command.
This all works as long as you’re using Ruby 1.8.x MRI version. As soon as you’d like to start using 1.9.x, you’re pretty much on your own. You have to compile RMagick gem for yourself. You ought to know that this is not an easy task under Windows. Yes, you can do it with the help of DevKit, but it’s still quite far of the simplest thing you’ll do within the day or two.
Imagine how hard it is to start using Win32-Screenshot gem with the full potential if every new user has to complete that process manually instead of just executing `gem install win32screenshot`.
In addition to the problems above the version 0.0.2 had also a little bug, which made capturing screenshots fail when they were at certain sizes.
Birthday Party Which Got Cancelled?
I have considered the possibility that most of the problems described above didn’t have any easy solutions at that time due to the missing libraries/tools which exist today, but the biggest problem was that all of these problems existed until May of 2010 when i started to clean it up. I guess Aslak just moved on to other platforms like OS X and didn’t have the time nor will to make it any better.
When browsing more of the Git history then there is one interesting commit:
The only difference pretty much in that version was a small change in the API - instead of returning a three-element array, a block had to be used for all the methods:
I liked it at first, but now i’m thinking that it made the API even worse because there wasn’t even possibility to use Array#[] and Array#last methods anymore to avoid using variables for width and height. You just had to always declare those variables. It was like you had to pay your bills, but you had to do it much often. I’m pretty sure that you understand how uncomfortable that makes you feel.
Change Of Winds
If i recall correctly then i started using the library in the end of 2007. I didn’t know much about the Ruby at the time so i just used it. I noticed that sometimes screenshots capturing failed and other times segmentation fault greeted me with a big smile, but it didn’t happen too often. I was using the library occasionally during the period of two years before these things really started to bug me.
I started by looking for a newer version of the gem, but got disappointed since the last version was still 0.0.2. At least RubyGems told me so. Then i found out that there was offered a patch for the bug of erratic failures of capturing the screenshots. I forked the Win32-Screenshot project, applied the patch and made a pull request to Aslak. Aslak didn’t want to accept the pull request, but offered me to maintain the gem myself. I was surprised by that offer and took it. It was a right thing to do in terms of reviving Win32-Screenshot if i’m thinking about that now. Aslak could just have ignored my pull request and the things would be probably be the same today.
Surfing On The Code
That essentially meant i could do whatever i liked with the library. I’ve added the patch for the bug which caused screenshot capturing to fail and started with replacing fragile Test-Unit tests with more robust RSpec specs.
Next step was to replace Ruby/DL with something else due to these segmentation faults. I didn’t think at first that there would be any problems when using win32-api gem. All usages of Ruby/DL got replaced one by one with win32-api until i realized that if i’d like to use Ruby 1.9 then this solution wouldn’t work either, since there wasn’t any pre-built win32-api gem for these versions of Ruby. At this point i discovered the wonderful ruby-ffi gem which also promised to give me support for JRuby. What a bargain! Again, all usages of win32-api got replaced with ruby-ffi and a support for all MRI versions of Ruby and JRuby was achieved.
I started to like how the code was turning more beautiful with each day and released version 0.0.4 on May 26, 2010. This version addressed those three critical show stoppers - failure of capturing screenshots, segmentation faults and compatibility with different Ruby versions. It felt almost perfect. I called it as “A Complete Overhaul”.
Highway To Better
After the release of version 0.0.4 i started to polish the code and add some additional methods to the API like #window_area and it’s friends, which allowed to capture an area of the window specified by the coordinates. Also, exact window title could now be used by specifying string instead of a regular expression. I got also some contributions from Roger Pack. I always love contributions, thank you!
From that point forward new versions were released quite often, until 0.0.8. At that moment the API was more or less the same as it was in 0.0.3 (the need to use blocks was still there), but just more methods were in the arsenal. Even methods which didn’t make anymore sense to have in the context of “capturing a screenshot”. For example there were some utility methods like #all_desktop_windows and #window_process_id, which just didn’t seem to fit in my mind in that gem.
Cleaning Leaves
That’s when i realized that i wanted to do a completely separate library for searching and retrieving information about the windows. I started development of RAutomation. I’ve written about that library in my previous post “Automating Windows and Their Controls With Ruby”.
Extermination Of Bad Bacteria
As written above then the bad dependencies for Win32-Screenshot included ImageMagick and RMagick. I tried to find a way to remove the need for dependencies which need to be installed separately of the gem. My research for possible options ended up with an unfortunate news that there just wasn’t any fast enough solutions to save files to PNG format with pure Ruby. The next best idea was to use MiniMagick, which is a Ruby library wrapping ImageMagick’s executables for image manipulation and saving to different formats. So if i could bundle all necessary ImageMagick’s libraries and binaries with the gem i’d be on the road.
You know what? I managed to do it! Starting from version 1.0.0 all necessary parts of ImageMagick are bundled with the gem which means that you don’t have to have ImageMagick nor RMagick installed to save screenshots into BMP, GIF, JPG or PNG formats with Win32-Screenshot! Now you just have to have Ruby installed and you can just execute `gem install win32screenshot` and not worry about anything else. Awesome, isn’t it?
The New Beginning
Removal of dependencies ImageMagick and RMagick made me think that maybe, just maybe, i could make Win32-Screenshot even better.
Creation of RAutomation allowed me to delete a lot of code from Win32-Screenshot. For example i was able to delete all the code related with searching the windows - “Capturing screenshots functionality shouldn’t know anything about how to find windows”, i thought. All that code, in better form of course, ended up in RAutomation. I just had to set RAutomation as a Win32-Screenshot’s dependency and start using it in the code.
By using RAutomation i got this idea of changing the API of Win32-Screenshot quite drastically to make it better, but of course break backwards compatibility as a side-effect. I started to tinker the code by trying out different ways of how the new API could look like. The result i came up with has only one method in the public API which parameters decide what to take screenshot of and an Image class which holds the bitmap data with allowing to save it to the disk. Check out the following examples:
The integration with RAutomation allows to use the same nice API for specifying what window to take a screenshot of. I’ve also made it possible to give a RAutomation window object directly as a parameter to make it all even more flexible without the need to add much complexity to the Win32-Screenshot’s own code. Also, the #write method used in the examples above works as you might expect - if you specify the image file extension as a “.png” then it will be saved into the PNG format. No need to specify anywhere explicitly that you really want it to be saved as a PNG format and not just with an extension of “.png”.
From Cradle to Adulthood
There is this other popular saying called “From Cradle To Grave”, but this post is not about that at all even if the title might have suggested it. This is about a birth and it’s journey to it’s adulthood of Win32-Screenshot. It made it to the version of 1.0.0 on December 16th of 2010. Since it is now following “Semantic Versioning” rules then i felt increasing the major version number due to the backwards incompatibility changes to it’s API. Also there’s a statement on the “Semantic Versioning” guidelines which just made it great to increase the version: “Version 1.0.0 defines the public API”. I’m declaring to the world that this is the public API and i’m really happy with the results code-wise and API-wise.
Thank you, Aslak for making it all possible! Happy holidays with screenshottin’ and don’t hesitate to give me any feedback!
One last thing - guess what happens if the following code is executed right now on my machine:
Of course glimpse of The Awesomeness will be saved to my disk with The Awesomeness itself. It’s almost as scary as running VM inside of another VM!
How would you automate windows and their controls like button and text fields if you had to? How would you do that in Ruby? I guess you wouldn’t. At least not in any user-friendly way.
Until now. I’ve created a Ruby library called RAutomation which allows you to control windows, retrieve different kind of information about them, fill text fields with desired jargon and click the buttons on them! That’s all via very user friendly API.
Let’s Start to RAutomate
For example, let’s fire up Internet Explorer so that it has File Save As dialog opened like seen on the picture below:
Now, let’s install RAutomation gem and start up an irb session so we can have our fun with that window:
If you’ve used browser automation tool called Watir before then the code above should seem awful lot similar. The thing is that RAutomation’s API is inspired by Watir’s clean and nice API. Awesome news, isn’t it?
You can also see that i’ve managed to find the window, made sure that it has a title, that it exists, is visible and has a window handle (hwnd). Nice.
Clicking the Button
Ok, let’s click the Save button because that’s what i want to do, right? I want to download RAutomation’s gem from the RubyGems website! That would sound just odd if i wouldn’t. Clickety, click…
Whoops. That was almost as easy as walking in the park. The following window appears to make sure that i really want to download the file and i really know where to put it:
Filling the Fields
If we’ve already come so far then what choice do we even have anymore? I guess we have to tell it where to save the file. Let’s do it!
Saving The File?
It’s also possible to search windows by regular expressions? Nice! Ok, let’s click now that final Save button. Oh, dang. I just realised that i already have this nice gem because i installed it with `gem install rautomation` early on. It would be just plain stupidity to download it again, especially like this. I guess i’ll just ditch the window instead and carry on with the knowledge of having this wonderful library already in my posession.
What About Popups?
Let’s pretend that after you closed the window above, the following threatening JavaScript popup appeared out of nowhere:
First of all, if you’re using Watir then make sure that you’re testing your page correctly. If that’s not the case, then by all means, take risks in your life once in a while and close that popup:
Where’s The Catch?
The catch is that not all kind of windows and platforms are supported. Yet. Currently only Windows operating system and windows using Windows’ native components are (fully) supported. But why did i emphasize on the “Yet”? That’s because RAutomation is built to allow cross-platform compatibility with easy extensibility by allowing to support all kind of different technologies. This is where the Adapter comes into the play.
What’s an Adapter?
RAutomation’s adapter is a technical component of the library being responsible for dealing with controlling windows and their controls on a specific operating system for specific technologies. As stated above then currently only Windows operating system is supported with two different adapters - :ffi and :autoit. By default :ffi adapter is used on Windows to execute Windows’ API functions directly. If there’s any need to change the adapter then it’s possible to specify another default one by using an environment variable called RAUTOMATION_ADAPTER or specifying different adapter for controlling specific window with the :adapter option:
Since i’ve set the environment variable to autoit then the first window is using adapter for AutoIt. The second one uses FFI instead since i specified it with an :adapter option. And of course they both point to the same physical Internet Explorer window.
How to Create New Adapters?
Since i’ve built RAutomation having all kinds of different platforms and technologies in mind, i’ve created a possibility to extend it relatively easily. If it’s possible to automate windows with Ruby directly or with the help of some external tools on the platform, then it should be possible to create a new Adapter for RAutomation. Just follow the steps below. I’d be happy to merge the results into the master.
Jarmo Pertman is an enthusiastic developer using the Ruby programming language. He is one of the core developers of the popular automated testing framework Watir. He is also responsible for some other libraries like WatirSplash, RAutomation, Win32::Screenshot and require_all. IT Really Matters is his personal blog where he tries to write about stuff that really matter in IT.