Getting rid of global variables
As I promised in two of my earlier posts - “The beginning of Watir’s RSpec html formatter” and “We need more to be shown in the reports?!” - i will show how to get rid of the 2 global variables which are in use so far:
- $browser - it is used to store Watir::Browser instance and it’s global because it is needed in RSpec’s WatirHtmlFormatter class for making screenshots and saving html of the pages upon spec failures.
- $formatter - it is used to store RSpec’s WatirHtmlFormatter class instance for making it possible to get spec specific file path locations when creating/saving files so they would be visible on the spec report.
In other words - they exist purely because there needs to be a “bridge” between RSpec’s formatter and the specs themselves. But there is a better way to accomplish this connection between of these two than using global variables (since they’re bad, m’kay).
Getting rid of the $browser
First, let’s replace every usage of $browser variable in the spec file with a @browser variable instead thus making it an instance variable. Instance variable is a good choice because it is accessible also in the it blocks when created in before :all block. After that WatirHtmlFormatter doesn’t know anything about the browser object. To pass the browser object to the formatter, there’s the possibility to use RSpec’s options hash. Unfortunately due to RSpec’s current limitations you have to use it in before :all, in after :each and in after :all blocks. First time for the cases when something fails in before :all block, second time when spec itself has failed and third time for failures in after :all. It might seem that all this is just not worth the effort. Well, maybe not, but here’s the current solution:
Now let’s replace all usages of $browser variable also to @browser in the WatirHtmlFormatter class. This doesn’t give us yet the browser object, but we just need to initialize the @browser variable from the options hash like this when spec failed:
Now we have a browser object accessible in formatter and in the specs without having to use any global variables which would just pollute the global object space.
Getting rid of the $formatter
Getting rid of the $formatter is even easier - we just need to get the correct formatter instance within the spec’s and that’s it. Because you can use multiple different formatters together when using RSpec then we need to find our specific formatter. It’s just an easy task of finding our formatter’s instance from the array of formatters. Let’s implement it as a method into our describe block so it’s accessible within the it blocks:
Now let’s just replace all usages of $formatter with a method call to formatter instead and we’re done. Don’t forget to delete assignment of $formatter variable in WatirHtmlFormatter class also. That’s it, now we have gotten rid of all global variables.
There are actually few problems with the current solution:
- What if i don’t want to run my tests with WatirHtmlFormatter but with some third kind of formatter or from IDE directly? Currently my spec file is strongly coupled with WatirHtmlFormatter and running specs without it wouldn’t work!
- It is still quite cumbersome to use RSpec’s options in 3 places altogether.
These are the problems which i should try to fix in some newer post. You can see the complete changes at GitHub.




2 years ago
