Advice on starting browser-based automation

On the Selenium-Users mailing list today, I got asked what recommendations I would give to a team just starting browser automation with Selenium on an agile project that had been running for 6 months. Not knowing anything about the project other than that, I had to limit my response to some very basic points that so far in my experience seem to apply well to many projects. (Note that this does not mean that they apply everywhere).

Here’s what I responded with – what else would you add?

Here are some recommendations that I’ve found to be generally applicable to automation projects:

  1. Figure out why you’re automating tests in general, and why you want to test through the browser. Reasons like “because it’s the cool thing to do” or “I’m looking to increase my skill set and make my resume better” are almost always not be the best choices from an organizational perspective. Reasons like “Testing is taking too long” or “we have too many testers” may not be good ones. “Accessing areas we can’t otherwise get to” or “Free up our manual testers to do more brain-engaged testing” might be. Every project differs though, so you really need to understand why you (or someone asking you to do automation) want to do it in the first place.
  2. Use PageObjects (google it to find information, both on the Selenium wiki and on various blogs). One of the benefits of using Page Objects is that it localizes all your interactions with actual pages to one location, and makes maintenance easier. You’re starting already behind if the project is 6 months in, and anything that makes maintenance easier is probably a good thing if you ever want to catch up.
  3. For new features, include the cost of automating the feature in the same story as building the feature. For existing features and infrastructure work, create separate stories on your backlog. Hopefully, you already have channels open where the team can work with the customer to get things the developers need (like refactoring or automated testing) but which don’t necessarily translate directly into new desired functionality for the customer (though they may enable new functionality later or provide other benefits that the customer also desires). If you do have them, use them for your automation, making sure the customer knows the benefits of doing automation (some of which should come from your reasons in point 1 above). If you don’t have those channels, then you need to develop them. Ultimately, the customer decides what they want to pay for, so you definitely want their agreement.
  4. If you’re following your agile methodology by the book, you probably have a team of generalists and be pairing. With generalists, there shouldn’t be a specific test automation person, and each person on the team should be expected to develop their own tests within the framework that evolves. Most actual projects I have seen haven’t been entirely this way, and there’s been some thought that it’s not even a worthwhile goal. If your team works this way, though, plan to pair with the other team members to get them started. If automation is built into the story cost, this should be easy. You can also request people pair with you on the backlog items when they get purchased for a sprint. Even if you are the “automation person” and the team isn’t going to write automation as they work on stories, getting the team to pair with you is a good plan. It helps build relationships with the rest of the team, it helps the team be more aware of what you’re doing (which means that in the choices where the developer is making a fairly arbitrary decision, they might choose the one that is more automation friendly), and you may find out about APIs or things like that that you can use to make your testing more efficient.
  5. Don’t get hung up on doing all the testing through the browser. Some testing needs to be done that way. Other testing can be accomplished just as well through lower layers of the application sometimes. If you understand your purpose and your tests, you should be able to analyze the tests and figure out where to best execute them.
  6. Treat your automation as a model of your problem domain and your application. In my current project, I actually have 2 models – one is entirely focused around the concepts that a doctor or nurse would use in describing what they need our system to do – they register a patient, they order tests and medications, they report results. This model has no knowledge of how things are implemented in our application. The second model focuses entirely on the implementation. It uses Page Objects to encapsulate each page, and each page knows only the tasks that can be performed on that page. My page objects generally aren’t even aware of each other (though there may be some of that for the navigation links). By isolating and decoupling these models, maintenance is reduced – if the implementation changes (which is more likely than the existing business logic changing), the business logic remains untouched.
  7. Plan to use the WebDriver interface (or Selenium RC if you need to use v1.x) rather than trying to record things in IDE. Use the recorder in IDE to quickly find possible ways to find a control, but don’t bother trying to start off with table-based recorded tests. You’ll find it increasingly difficult to keep up as you want to go beyond what’s possible through the Selenese commands.
  8. Treat your automation with the same respect and processes as your application code. Code review, pair on it, write unit tests for it, put it in source control – everything. There’s lots of potential pitfalls when developing code of any sort, and we as automators should use solutions that already exist where it makes sense to do so.
  9. Don’t blindly take your manual tests and automate them. While some manual tests may be suitable for automation, others aren’t – they may take a lot of code to accomplish something that a manual tester could do easily, they may be test cases that don’t provide enough value to be worth automating, or there may be some other reason to keep them manual. Make sure you’re not wasting time automating things that don’t need. You may also find that the automation tool allows you to reach places that your manual tests couldn’t get, so there may be additional tests that it makes sense to automate that aren’t in your manual tests as well.
  10. In places where you can do so without devaluing the test, introduce variation in your tests. Static automation that always does the exact same thing in the exact same way with the exact same data commonly tends to find defects when you create it and then never again (or rarely again). Sometimes this might be ok – if your sales people have a canned demo script they always use, and you create automation based on that to ensure that your sales people don’t get embarrassed in front of customers, you probably want the test to exactly follow the script. If, however, you’re looking to actually test functionality, adding variance means that your tests have a greater chance of finding bugs when they try something new. Possible ways for adding variance include using random data, path variance, and randomly ordering your test execution. By randomizing test data, you are looking for things like incorrect assumptions – for example, in our app, it shouldn’t matter if a patient being admitted to the hospital is male or female, whether they’re 18 or 80 years old, or whether they know (and provide) their birthdate. We may decide that these things don’t need separate test cases, or we may not even think of them. If our expectation is wrong, however, we’d like to know that. It’s possible that someone coded in a dependency that is a bug or wasn’t communicated to the team or whatever. By varying our test data so that we hit some of that variance naturally over the course of several test runs, we get a wider degree of coverage and might stumble across something like that. Of course, we might miss it too – if the bug only occurs for an 80-year old woman who doesn’t give a birthdate, we might never pick that combination. If our test is hardcoded to use a 36-year old male with a birthdate given though, we’ll definitely never find it with our test. Adding variance to the paths you take uses a similar idea. Say, for example, you needed to copy some text to the clipboard as a step in a test. There are lots of ways to copy text once it’s selected –you can press Ctrl-C, you can select “Copy” off the Edit menu, you can right click on the selection and choose “Copy”, or maybe there’s a toolbar with a copy button in your application. If you’re not specifically testing the copy functionality, you probably don’t generally care which method is used, as long as the text gets to the clipboard. It’s common for automators to pick one way to accomplish something, and use that – maybe it’s the method the automator uses themselves, maybe it’s the easiest to automate, maybe it’s the one specified in the first test case that needs that functionality. Whatever the reason, the tests are now more constrained. If you instead provide a way to vary this behavior each time you need it (either randomly or with some intelligence involved to choose the least used path each time or something), you have the possibility of catching bugs where one path to achieve the task doesn’t work the same as the other paths. Finally, varying the order of your tests gives you the possibility of finding interaction bugs between tests. Providing this variance requires that each test be independent, and this kind of variance isn’t one I’ve looked at a lot yet, but if you can provide it, your tests may have more defect-finding power. For each of these variance techniques, though, there may be test cases where you specifically don’t want to vary things – it’s essential to your tests that a task is accomplished a certain way, or that the data used meets certain criteria, or whatever – this is another area where analyzing and understanding your tests is important. You don’t want to either over-specify your tests and constrain them in ways that aren’t necessary, but you don’t want to under-specify them either and miss what you’re trying to test.
  11. Design in a way to repeat your tests even with the variance. Even though adding variance to your tests increases their power, there will likely still be times when you do want to exactly repeat the tests (for verifying bugs, for example). Build in this repeatability from the beginning – in my case, my two models talk by the conceptual model sending Command objects to the implementation model. These Command objects contain the action to perform, the data needed to do that action, and the path taken to perform that application (which sub-models, pages, and functions were performed). These commands then get serialized out where a runner can later deserialize them and rerun the tests with all the same data and actions.
  12. In a similar vein, run your tests from the beginning on all the platforms you know you want to test against. Cover the browsers and operating systems that you can predict you want to run against right from the start, so that as you’re developing, you’re trying the code on all of them and not going to run into major surprises later when you absolutely need to run the test in a platform you haven’t tried before and you find some XPath or behavior differences.
Facebook Twitter Linkedin Digg Reddit Stumbleupon Tumblr Posterous Email
Posted in Uncategorized | 1 Comment

Guest Post: .Net Headless browser options

Jim Evans is one of the committers for the Selenium project. He works a lot with the .Net bindings and the support for Internet Explorer. He sent out a post today to the selenium-developers mailing list about work he’s done investigating headless browser options. He then commented in the #selenium IRC channel that it perhaps would have been better served as a blog post. Since he doesn’t have a blog, I offered to let him post as a guest author here and he accepted. You can find Jim on Twitter at @jimevansmusic or contact him via email at jamesdothdotevansdotjratgmaildotcom. The remainder of this post was written by Jim. Thanks, Jim!

There was recently a post to one of the Selenium mailing lists about accepting a .NET version (via IKVM) of the HtmlUnit driver to use a so-called “native” .NET implementation rather than relying on the Java Selenium server and the RemoteWebDriver class. There’s really nothing quite like HtmlUnit in the .NET space. I understand the impulse not to want to introduce non-.NET stuff into a .NET shop’s development environment. At one time I had many of the same concerns, but I’ve come around to Simon Stewart’s points of “it’s Just Another Binary” and “nobody actually browses the web with a headless browser”. However, I also realize that using a Java .jar isn’t just an xcopy deployment if you don’t already have the Java runtime installed, and in a “pure” (whatever that means) .NET shop, you may not.

Because of that institutional resistance to Java at some places, I’ve spent some time looking into alternative “headless” projects. Here’s a summary of what I’ve found:

XBrowser – I actually started a headless .NET browser called Crane, but abandoned it when Nathan Ridley contacted me about his XBrowser project. At one time, he was still using my .NET HTML parser. Good chap, but very busy, and the .NET JavaScript implementations up to this point haven’t been up to the task, so no JS engine yet, and no activity on the project in 6 months. One thing I learned while working on the project is that creating a web browser is bloody *hard*. The project is pretty much lying fallow at this point, so feel free to fork it and run with it if you’d like to pick up the ball with this one.

WebKitDriver – This project is referenced on the Selenium project Google Code home page, and uses a headless WebKit implementation. That means it uses a “real” browser engine implementation as WebKit is used by Safari and Chrome. The bad news is that it only has Java bindings, and there seems to be little response to pressure from outside the project to change that.

Envjs – This is a JavaScript implementation, originally started by John Resig (of jQuery fame). Needs a .NET JavaScript REPL and some custom JavaScript work to be accessible from .NET.

Phantom.js – Another headless WebKit implementation, but with a JavaScript API, implemented as a C++ executable, compiled for specific platforms. It’s downside is that it doesn’t act as a resident process that you can communicate with and control. Rather, it runs a single JavaScript script, then exits. Having said that, there is an issue in their issue list to create a WebDriver-compliant driver, and the project is under active development. Built statically, this would amount to an xcopy-deployable project in a Windows environment.

webdriver-zombie – This is a WebDriver implementation built to drive the Zombie.js headless browser. This project is brand-new. Like the first commit was yesterday. It’s based on node.js, which is getting lots of pub lately. That doesn’t help Windows users in the slightest at present, but the node project has a stated goal of native Windows support (experimental in 0.5, stable in 0.6), so there’s potential there. When (if) the native Windows support materializes for node, this would also amount to an xcopy-deployable project.

So if you work in a .NET-only shop, and an xcopy-deployable binary solution is okay with your development team, there are a couple of options under development that show promise, even if they’re not yet available. Contacting the owners of those projects and getting involved would probably speed up the process of getting WebDriver-compliant drivers built and available. If you can talk your development department into an installable solution, you can use HtmlUnit via RemoteWebDriver today. If they’re going to insist on a .NET-only binary, you can continue down the path of an IKVM solution, or you can write your own headless browser, maybe building on the foundation of Crane/XBrowser. In any case, I wouldn’t expect any of these solutions to land in the WebDriver trunk anytime soon, but I suspect the Selenium ecosystem is large enough to encompass other projects that provide different implementations of the Selenium WebDriver APIs, even as independent OSS projects.

Facebook Twitter Linkedin Digg Reddit Stumbleupon Tumblr Posterous Email
Posted in Automated Testing | Tagged , , , , , , , , , | 3 Comments

My Selenium Conference talk video now posted!

The video from my talk at this year’s Selenium Conference is now posted on YouTube. You can watch it here. I haven’t watched it yet, but I know we ran into some technical difficulties recording the screen during the talk, so as a reminder, the slides to go with the talk are available here should you need them.

I’d love to know what you think about the talk – both the contents and the talk itself!

Facebook Twitter Linkedin Digg Reddit Stumbleupon Tumblr Posterous Email
Posted in Automated Testing | Leave a comment

Test Automation Architecture: Our Application Under Test

After looking around a little to figure out what would be a good web application to use as Entaggle Logothe public example of my planned series digging deep into a test automation architecture, I’ve hit on the perfect choice: Entaggle.com

Entaggle is the brain child of Elisabeth Hendrickson. I had the chance to visit with Elisabeth while I was in San Francisco at her Agilistry studio, and she showed me what she’s building. Entaggle is a good size system for these examples, but at the same time is a real system with real functionality. It involves multiple pages, has some dynamic content, but isn’t so complex that it takes a long time to understand the functionality. It also has the advantage of having a staging server publicly available which allows us to test it without causing problems in production, and which Elisabeth has given me permission to use for the purposes of these posts. (If these blog posts lead you to want to test the entaggle site in other ways, PLEASE continue using the staging server for your tests so that she can keep the production server clean.)

For those of you who are unaware of the entaggle site, the site focuses around the idea of crowd-sourced “certification”. Once you register for the site, people can apply tags to you (or anyone else registered for the site). You can also tag yourself. These tags may help describe the relationship between the tagger and taggee (as in “Someone I’ve met in person” or “Someone I follow on Twitter”), they may describe attributes of the taggee (“A Clean Coder” or “Test Obsessed”) or they could be a hybrid of both (as “Someone I’d like to work with” is, given that it implies a measure of respect for the taggee but also reflects attributes of the tagger as well). Once a tag is defined, the person defining it can make the tag publicly settable (so that anyone can tag anyone else with it), settable only by the taggee (so you can apply it to yourself, but not to anyone else, allowing self-identification), or restrict the tag to a small group of people allowed to give that tag to people to avoid dilution of the tag. Once a tagger adds a tag to a taggee, the taggee has to first accept the tag before it shows up anywhere publicly (unless the tagger and taggee are the same person). This prevents someone from having to deal with incorrect or inappropriate tags applied to them. The site’s usage guidelines also limit the site to positive, real, and professionally oriented tags, designed to keep the site a pleasure to visit and avoid having it become a race to the bottom of mud-slinging and negative feelings.

I really like what Elisabeth is doing with the site. I think it’s a great way to harness our social networks. If you and I have a relationship, and show feelings of respect for each other in a positive way, then everyone who knows only one of us can see those respect indications and have better knowledge of the other person.

I was listening to the Quirks and Quarks podcast the other day, from Canada’s CBC (and specifically, the episode from April 16). In the last segment of the show, the host, Bob MacDonald, was talking to Dr. Kim Hill from Arizona State University. Dr. Hill is an anthropologist and was talking about how the fact that it was just as likely for young males to leave their family groups to find mates as it was for young females in early humans (in contrast to many ape species where it’s generally young females who leave the group. never to return) that allowed us to develop and achieve the accomplishments we’ve done as a species. In addition to both genders being the ones leaving, once children were conceived, the male was remaining to aid in the rearing of the children, and there were also more instances of couples going back together and spending time with the groups one of the couple had originally left. These elements together combined meant that the other members of the family group recognized that both family groups had interest in the survival of the children, and so were less apt to fight with each other. Because of networks like this, one human may interact with thousands of people during their lifetime. A typical chimpanzee (where the young females leave the family group after which there is little to no interaction across groups) may only interact with 15 other chimps in their lifetime. This bridge then expands outwards as different members of one group connect with members of different groups and makes cooperation much more possible, and allows us to accomplish things like space shuttles, which no one person could ever achieve on their own.

I think that Entaggle is fostering a similar sort of thing. To some extent, interactions like this have been going on for a long time – people give recommendations on others and use the source of recommendations they receive to add or subtract weight from those recommendations. Entaggle makes these interactions more visible and public, and I think this may prove a foundation for even more cooperation and communication and help us achieve even greater things!

So, that’s Entaggle. Elisabeth is still hard at work building out new features, and is actively soliciting feedback on the site and how it should grow. In the coming posts, I’ll start building out some automation around the site. (For the record, Elisabeth already has a great set of tests for the site, and doesn’t need my help with them. She’s graciously allowed me to make more tests, which she is free to merge into her suite as and if she wants.) I probably won’t create an entire test suite, but I’ll be creating enough to illustrate all the points I want to make. In the meantime, feel free to register at the site and try it out (remembering to use the production server for real tags and keep test data to the staging server at staging.entaggle.com). If you’re at a loss for who to tag, you could always tag yourself as a reader of testerthoughts.com! Feel free to tag Heather or me as well too, if you like!

Next post, we’ll dig into getting things set up for the automation, and after that, we’re into code!

 

Facebook Twitter Linkedin Digg Reddit Stumbleupon Tumblr Posterous Email
Posted in Social Connections, Testing | Tagged , , , , , , | Leave a comment