Posts Tagged ‘automation framework’

The new job (well, not so new now, but in any case my latest job) uses quite a bit of tech I’d not dug into previously. As far as source control goes, I’m used to centralised SC like SVN (or even CVS in a pinch), so getting my head around a distributed model (Git) took some doing (more work required there, but that’s fodder for a different post). Working with a new language and framework as well – I hadn’t touched Ruby on rails up to now, which was stupid of me – I’m finding it pretty freaking awesome for the most part.

It’s taken me longer than I thought to come up to speed. I’ve been scraping the rust off my unix-fu and with unfettered access to the codebase and the command line, I feel like a long-lost missing limb has been reattached. Between that and the whole ‘learning new stuff’ thing, I’ve not had much time for anything else. There seems to be light at the end of the tunnel though. I’m grokking more of the code base and starting to make some useful code contributions.

One of the things that I’m trying to do at the moment is put a little bit of structure in the way that the business group and the development group communicate. Right now there is lots and lots of communication, which is great. The confusion comes in where the lines blur between the business telling dev what they want and going to the extent of speccing out everything in such minute detail that there’s not much design work left to be done by the dev group. That might not really sound like a problem to some, but in practice I’ve found that it can make the dev guys feel micromanaged or like their opinion is not required/valued – especially when design-level decisions are architecturally difficult to implement. If non-tech design reaches too far and gets it wrong, it can mean wasted time and effort either for them when the developer rejects it, or for both if the developer codes it in order to prove the point. The thing I love about my current place is that there are no passengers, and this stuff tends to get worked out, but I think I can do more.

This is where I am hoping that Cucumber will help out. If I can put together a series of tests that step out the current behaviour with a DSL that both the business side and tech side can build their communication around, then I suspect we will find it a little easier to step through the desired behaviour in enough detail to be clear about functionality while leaving the dev guys to work out the implementation. It’s not the only reason I want to use Cucumber, but I do have high hopes in this area. It probably won’t hurt that people will be able to see this stuff turn into checks that can be executed automatically. The key is still in the communication. I’m looking to make the clarity of that communication easier.

Cucumber is new tech to me as well. Conceptually I get it, but it’s different when you start to get your hands dirty. After a lot of reading, I decided to go with Cucumber, Capybara and at this stage, I think a combination of Selenium and TestUnit (Ruby’s in-built unit testing framework). I’m a Capybara noob as well, so I’m up to my elbows in new stuff and loving it. Mostly. Sorta. Apart from the frustrating bits.

Almost the entirety of the literature I’ve found on this setup is for BDD – which is to be expected, given that’s what its for. All of the setup and how-to stuff is for building stuff that doesn’t exist yet. Great if you’re building from scratch, but not super helpful if you have an existing code base you want to fit tests to.

I had an utter bastard of a time getting Cucumber and Capybara to work at all. Granted that it’s probably because I’m working with code that does a few unusual things, but I didn’t expect quite as much screwing around as I had to do – so, I’m going to detail it here in case there are any other poor bastards out there who are trying something similar. Hopefully this will save you some frustration.

My setup is (as of writing) Ubuntu 10.4, using rails 2. I already have selenium installed, and the installation of that is not arduous, so I’m going to omit that part.

I installed the following gems:

libxml2 libxml2-dev libxslt1-dev
gherkin cucumber cucumber-rails nokogiri capybara database-cleaner

I’ve listed some that should be pulled in automatically by other gems’ dependencies. For instance, gherkin should be installed when installing cucumber, but for some reason I had to do it manually. YMMV.

After installing the requisite gems, it should be a simple matter of generating all of the cucumber goodness from the root of your rails project

(ruby) script/generate cucumber –capybara
(you can add other options if you want to have them built in)

If all your bits and pieces are installed correctly, you should see a bunch of files and directories get created.

Here are some things that tripped me up:
I thought I might do some work with rspec as well, so I pulled those down. If you’re thinking along the same lines, then Cucumber seems to barf if you install anything beyond rspec 1.3.3
I also had to mess around with the dependencies for the json gem in my project as cucumber seems quite particular about wanting 1.4.6

By default, cucumber will clean the database after each run (as is generally considered good automation practice). In my case however, I have enough stuff in the db that it doesn’t make sense right now to load from scratch or mock the bits I need. Maybe down the track but for the moment I’ve just switched this off in the environment file (more on this shortly).

Anyway, moving on. From root, there should now be a features directory. edit features/support/env.rb
You can either make your settings changes in here, or in another file and require it from here. This file is automatically generated, so if you plan on making a lot of changes here or you think you’ll have cause to regenerate this file, the latter might be a better option.

Here are the changes I put in

Capybara.default_selector = :css
Capybara.run_server = false
Capybara.app_host = <url of my testing area>
Capybara.javascript_driver = :selenium

One of the things that really screwed me around was not realising that Cucumber starts its own webserver and runs on that. I tried pointing it at the server instance that Rails kicks off, only to find that things were falling over and there was nothing in my logs to tell me why. I felt like a complete moron once I did find out, but then again, the docco in this area appears to be awfully light so I don’t feel too bad. Anyway – be warned. If you don’t want Cucumber to use its own webserver, you need to tell it so explicitly.

As I said, there’s bugger all out there right now on retrofitting scripts for an existing code base. It sounds like it’d be easy, right? The code and functionality is already there, so skip the red/green/refactor bit and go straight to green, right? Not really.

Rather than conceptually pre-fabricating your functionality, you get to look through your existing functionality, decide what is most important to test, work out where you need to retroactively install test hooks and build use cases that serve a business purpose, while not getting lost down a rabbit hole around functionality that currently exists, but perhaps doesn’t work quite how it should. Yay! Given that there is the potential for test to ‘just light up green’ when you write them, I’ve also found it a good idea to write checks that fail so you know they’re actually doing something, then correcting them – it sort of keeps the spirit of BDD/TDD even if you’re not driving any development just at this point.

Retrofitting Cucumber tests to your site is not as simple as it might sound. I am hopeful that it will be rewarding. It’s a little too early to tell just yet, but the signs are positive. If there’s any interest, I may follow up with a post about some more of the specifics of the actual hands-on retrofitting bit. If you have questions, fire away.

I’m having a lot of fun with this Selenium gig (shh, don’t tell anyone). There have been a few yaks shaved and I’ve seen the inside of some rabbit holes, but there seems to be a lot of good material online to guide you.

At this point, I’m running my tests directly from eclipse, though we’ll be looking to kick them off with Ant in the near future. I’ll jump off that bridge when I get to it.

LoggingSelenium
I’ve set up loggingSelenium to log test execution. I’m not sure what its current development / support status is over at SourceForge. The documentation it comes with is not real flash, but there’s a decent example here (via here). I have made a couple of custom modifications to the source of loggingSelenium as there are a few gripes that I have with it.
Some of the pluses are:

  • it will automatically grab screenshots for you when your scripts bork.
  • it color-codes your asserts and failures
  • it can wrap JUnit asserts and log them alongside your selenium commands.

Some of the not-so-good things are

  • it requires a hardcoded path for writing output
  • it looks like it’s geared to non-windows systems, given that out of the box, the screenshot links in html output don’t work.
  • the color of failed selenium asserts is different to JUnit asserts, the former being an easy-to-miss beige color.

The mods I made were quick and dirty hacks, one to fix the screenshot link and the other to make the beige color more noticeable. If I find myself with a spare second I want to get rid of the need to use a hardcoded path, or at least make it more nicely configurable. I also want to add a color selector so you can customise your output.

Autodocumentation
I’ve set up doxygen to generate documentation from code comments. I’ve not hooked it up to anything yet, but either an SVN pre-commit hook or getting ant to kick it off shouldn’t be a problem.

Test Structure
JUnit 4 does not require you to extend tests from a test class, which is quite nice, actually. Instead, I have written a parent class for my tests to extend from. The parent holds all of the setup and most of the methods that drive the tests themselves.

Currently I’m writing one test per class. The class contains a single method containing calls to methods in the parent and nothing else, so it ends up looking like a set of test case steps. The parent has the potential to get quite big, so as test case numbers grow, it’s likely that I’ll add further abstract classes between the current parent and the tests to group them more reasonably.

I’m importing data via Properties as a resource stream. I have data that is used to drive the tests and data that is variable, but predictably constrained. For instance, I use a vehicle class number as a driver. The class number refers to a class of vehicle whose data is stored against that number. Depending on the number selected, different vehicle data is populated during setup.

On the subject of Properties – If you’re developing in a language that uses double-byte characters (such as Japanese), if you are generating your Properties files as flat files, you’ll need to run native2ascii on them to convert your double-byte code to unicode. Otherwise, they will not be properly interpreted and things will fall over.

I have just started playing around with the @Parameterised tag and @RunWith(Parameterized.class) to get iteration working with data variation. I haven’t decided quite how I’ll run with that yet. I could do this at a suite level and control iterations of tests by feeding data to them, or I can have each test take care of its own iteration by setting up parameterisation within the tests’ parent class.

Browser setup
I’m doing mobile emulator testing at the moment, so I’ve set up a firefox profile specifically for it. I’m using the user.js file to alter the plugin config so that the browser starts up with the plugin activated and a particular device switched on.

When starting seleniumRC, I specify this browser profile specifically so it is automatically used when firing up the browser. I was hoping to be able to change device type on the fly by mucking around with chrome urls, but I’ve not found an elegant way to do this yet. Instead, I am swapping the user.js file out whenever I need to change. Essentially, you can load up the user.js file with calls to your plugins to switch them on/off and configure them based on what configuration the plugin makes available.

It’ll end up looking something like

user_pref(“<plugin.configItem1″, “value1″);
user_pref(“<plugin.configItem2″, “value2″);

You can hunt down config items by typing about:config into your browser. Any config item that is not set will be invisible however, so I ended up looking through the plugin’s jar file to see what else I could see.

So at this point, I have a loose collection of parts that are not quite all tied together but it’s getting there.
Other things I’m contemplating in the not too distant future is a web front-end so non-technical testers can select test suites and kick them off at will.

While I haven’t gone into code-level specifics, the links should provide a fair amount of detail. Let me know if there’s something I’ve not explained so well. If you have comments or questions re any of this, I’d love to hear it.

To borrow from Groucho Marx – QTP, I’ve had a wonderful time, but  this wasn’t it.

So thankfully I’ve been able to step away from QTP for the moment. Given that QTP doesn’t recognise Firefox so well after v3.6, and since we use a firefox plugin for most of our mobile testing (FireMobileSimulator), yours truly gets to switch to Selenium instead. I’m thankful for having had the opportunity to work on QTP, mostly so I have a better understanding of its limitations and shortcomings. I can argue more coherently against what seems to be in most cases, a ridiculous waste of money.

I view QTP a bit like one of those unfortunate bears in a Chinese bile farm. You can see how at birth it had the potential to be something majestic and powerful, but instead it languishes in a cage, irreparably twisted and deformed by years of abuse by the ignorant.

In comparison, Selenium while not without challenges of its own, has been by and large a real joy to use. For starters, having any number of fully fledged languages to work in is almost unbelievable after having toiled in VBScript land for far too long. In fact, the first problem I faced was which language do I go with?

I ended up choosing Java and JUnit, mostly because it’s what the current dev team codes with, and I simply cannot be arsed copping the flak I would get from management for introducing another language into the picture (as wonderful as jruby and jython are, I’m sure).

I didn’t realise quite how much thinking in VBS had stunted my thinking in other languages. I do a bit of coding in my spare time, but as far as automation coding goes, it took me a good few days to get comfortable again remembering the power that a real language gives you. I was all set to start importing test data from excel when a timely tweet (and subsequent blog post) from Adam Goucher reminded me that Java has these nifty things called Properties that you can import. (This is why tools like twitter should be allowed in the workplace btw – okay my RSS reader would have picked it up, but not before I’d wasted a lot of time).

It’s been a bit over 3 years since I last looked at Selenium. It doesn’t ‘feel’ all that different, but it does seem a lot easier to work with than I remember it being. Within a couple of days I’d whipped together a script to cut down some checks that took 4 hours manually to a little under 2 minutes. W00t.

I added loggingSelenium to my test setup and now have some pretty colours that light up for people who are impressed by that sort of thing. I’m now in the process of putting together a few more tests and a framework that will support them and their inevitable expansion.

There are a bunch of setup how-to’s out there, so I won’t be doing that, but I will drag together some of the more useful links that I’ve found. Stay tuned :)

On the suspicion that my last post amounted to a bunch of word salad for a few, let me see if I can add some clarity by describing the basic hierarchy I’m using for my framework.

At the top level, I have a suite control script that looks like this:

doSetup   ‘Calls to set up data and environmental variables and such like

Call Script1
Call Script2
…
Call Script n

Each script that is called is some sort of major transaction that an end-user would recognise.

If you missed the update I made to my last post, I’ve moved a number of function libraries to classes to lessen the amount of coupling required between the ValidationManager and the scripts. There is a small overhead involved in that the relevant class has to be instantiated at the start of the script. For debugging purposes, I have also added a commented-out debug section that calls the setup function that the suite control script does. Each script looks a bit like this:

‘#begin debug
‘doSetup    ‘uncomment this if debugging this script
‘#end debug

Transaction = loadTransaction    ‘This is the instantiation of the class that holds the Transaction’s functions

Transaction.function1
Transaction.function2
SharedFunction
Transaction.function3
…
Transaction.function n

For functions that are shared across multiple transactions, I have left them as a standard function library. On the plus side, the Transaction namespace aids clarity and lets you know where your functions live. On the downside, you can no longer access them by using the right-click->go to function definition option. No biggie imho.

The transaction classes aren’t that much different from your standard function library other than the fact that they’re wrapped in a class definition and there’s a bit of setup stuff at the start.

Class Transaction

Dim VerificationManager

Private Sub Class_Initialize()
VerificationManager = loadVerificationManager   ‘Here’s where the verification manager is instantiated
EndSub

Public Sub Function1
do.something
VerificationManager.CalculateExpectedState(“someAction”)
do.someAction
VerificationManager.Verify(“someAction”)
do.somethingElse

End Sub

…

End Class

I’ve still not gotten the all-clear to post the verification manager code, but as mentioned previously, it is a class also. There are 4 methods; 1 for setup and 3 relating to verification.

CalculateExpectedState calls a file called “someAction”. someAction calls a setup routine that creates a new dataSheet, also called someAction and populates it with expected data.
Back in the class method, the action takes place, at which point we return to the verification manager when Verify is called.

Verify calls the someAction file which calls a second routine that gathers data from the app and does any calculations required and stores the results in the someAction dataSheet. Verify then calls a diff function that compares the expected and actual results and reports. Finally, verify calls UpdateMasterData, which compares the actual data with the master data sheet and replaces anything that was changed.

At this point, there is a new data sheet created for each different call to the verification manager. This has the potential to get out of hand as the number of verification points increases. I’m thinking of using a single sheet and dumping the results to a file at the end of each verification. I’ll see what else occurs to me as I go.

I promised to talk a bit about what I’m doing with data. I still need to cover that. I’ve been having fun trying to define heuristics to govern where the data should drive the scripts and where I should handle variance programatically. I think I have something that works. We shall see.

One of the things I really like about the Logical Functional Model is the concept of removing verification code from the execution code. Another is updating verification data on the fly to reduce the likelihood of false positives.

These concepts are especially appealing since QTP’s in-built verification method is not worth using. Verification points are script-specific. You can’t update and re-use them multiple times within a script or share them across multiple scripts. Maintenance nightmare.

Instead, what I have done is to write a custom verification layer. Here’s how it works. At the start of my control script, I instantiate the VerificationManager, which is a class I have written to take care of verification code.

If a function that I am executing needs to do any verification, I pass the class to it by reference UPDATE: I’ve switched how I call this now. I’ve turned function libraries into classes. Each class instantiates the VerificationManager as part of its own setup and the functions can then call the VerificationManager without having to handle it as a parameter. There are several reasons for this – I’ll go into these in an upcoming post.

Within the function (now class method), there are 2 calls to the VerificationManager, one to set up the expected data and another to retrieve the actual data.

Where you call these depends on what setup you need to do beforehand. If you’re getting expected values from the application under test, you’ll want to do so before you execute the code you want to verify. If you’re grabbing your expected data from the data table, then you can do it just before you call the code to retrieve the actual data.

That probably looks like word salad on first read through. If you haven’t already, I strongly suggest you take a look at the verification chapter in Michael Hunter’s description of the LFM. It took me a couple of read-throughs to really get it, but once I did, I was impressed.

How does the VerificationManager work?
It’s as generic as I can make it. It has 4 methods.

  • CalculateExpectedState(someAction)
  • Verify(someAction)
  • Diff
  • UpdateMasterData

CalculateExpectedData and Verify both make calls to files called StateGenerators. It is the role of the StateGenerators to hold the logic and fetch the data required to do the verification. In simple terms, they are function libraries that are loaded at runtime by the VerificationManager.

You’ll notice that the parameter for each of these methods is the same. They call the same StateGenerator and this parameter tells them what name to look for. The VerificationManager loads the StateGenerator specified and executes one of two functions – either a ‘setExpectedState’ or ‘getActualState’ function.

Each call to the verification manager will use a different name. There will be one StateGenerator for each call. The StateGenerators all have 2 functions, all of them identically named. What they contain differs based on what they need to verify. There might be a series of calls to the global data table to grab data that needs to be checked, or there could be logic to calculate an expected value from a set of other values.

The setExpectedState function creates a new data sheet to hold expected data. If any of this data comes from the GlobalDataTable, then the new data sheet has an identically named column. Likewise if there are any new columns that need to be added to the Global data table for future reference, then this happens here too.

Once the code to be verified has executed, the call to Verify happens. Verify grabs expected values from the application under test and adds them to the second line of the expected data column. It then calls Diff, which (as the name suggests), compares each value of row 1 with the values in row 2.

The diff method logs both successful comparisons and failures by making a call to the standard QTP reporter. Right now, I’m going for simplicity; there’s a lot more you could do with this if you wanted. You could add weights to each verification item and log a severity message based on the weight of the failed item. You could call a custom reporter (which is a good idea, given that any time you tell QTP of a failure, it treats the entire script as failed). You get the idea.

Lastly, the Diff method calls UpdateMasterData. This routine simply loops over any difference and checks the global data table for columns of the same name. If they exist, the global data table is updated with the new value, so that if any comparison is made against it later in the script, it will be made against what we see in the system during this run.

I’ve asked my current employer for permission to post the code, as it’s completely abstract and contains no proprietary data. No word on whether they’ll go for that yet, but if so, I’ll update that here. Hopefully there’s enough here already to be useful.