Menu

Monthly Archives: April 2010

My newest venture resumelink.org is moving along nicely. I’ve got a pretty good grip on the features and some interesting partnership prospects. I’ve got a timeline for debut (I’m targeting June 1) with a very basic feature set.

upload your resume

create a personalized URL

(maybe) create a profile

(probably not yet) build a resume online

(definitely not yet) community features

(possibly) integration with a “competitor”

templates and ads are out for now, but I want to have the infrastructure in place

conversion can be done as a manual process

custom stats are out, but you can probably use google analytics or some blog tools

I’ll be looking for feature requests from recruiters, employers, and other professionals (like resume writers) after launch

But now I need to start thinking about appearances. The current home page is atrocious (I designed it) and there is no logo. The copy isn’t great either, but the main point was to get some content areas and show the general concept.

I created a contest over at 99 designs and haven’t really seen anything good yet (but it’s only been 1 day). If you’re a graphical designer and you are interested, head on over. Or if contests or “spec” work aren’t your thing, and you’re still interested, let me know.

My own logo ideas are literally drawn on scraps of paper (and in one case, a napkin). I scanned them and uploaded the images here:

You are then specifying the requirement as a test, which then knows how to not only navigate, but set up the correct scenario, including registering a user with specific parameters, and a positive or negative outcome. You can then easily implement

I haven’t really gotten the chance to explore that yet, since the first obstacle to that is breaking out the XUnit style framework, and that will take some work. But you could then build underlying test methods with selenium, using chain of command.

verify() is a method that essentially creates & returns a test conditions, analogous to an xunit test method.

$test is then equivalent to a TestCase class. Helper methods can be included at the test level, including setup and teardown, as well as any test domain specific helpers. You then have a clearer demarcation of what to put in a test — conditions that share the test domain. Ideally, only tests that are identical except for isolatable scenarios that are easily specified in a table.

$user is the object under test (or principal actor) wich is passed to the verify(), but that’s really just an implementation decision. It defines the base state and a test condition should pass or fail based on this object’s state.

with_membership($membership_category) is a modifier to the test condition. It establishes the state which distinguishes a scenario. There can be multiple modifiers chained together and they should each return the condition.

can()/cant() signifies an expected outcome. You can create methods with any name that establish this such as should()/shouldnt(), has()/doesnt_have(), is_less_than($number), etc. It determines the assert.

access_premium_content() is the meat of your test. It contains the steps needed to get to your assert that are outside the state setup. It defines the condition that each scenario will test against.

You can also chain expected outcomes with and() or but(), but you shouldn’t use more than 1 or 2 of these.

BDD tools like JBehave and RSPEC/Cucumber try to get here, but they’re more geared towards unit tests, and I haven’t really been satisfied with them. They seem more geared towards establishing a particular syntax that only developers can write that analysts can read.

I don’t know that this wouldn’t fall down the same path in implementation. But my goal would be maintainability, and clarity of coverage. Readability is ancillary and expressiveness shouldn’t be sacrificed for whitespace or any particular methodology’s phrasings.

Like this:

You reach a point when you realize you should be blogging about something. Today that point for me is 3 tweeterings and 2 requests for elaboration. I should just be grateful that smartpeople are listening to what I say (though it should encourage me to shut up quicker).

So let’s start with the twitter text:

Last night, I lay awake thinking about a problem I have at work (using Selenium for test automation), and not getting paid to lie awake. This morning I came in and posted a practical compromise on my principals that page objects are good, but should be kept as dumb as possible.

Looking back at my tweets, I realize that I inadvertantly conflate smart/dumb with dynamic/static. The two are not necessarily similar, and dynamic isn’t necessarily synonymous with “instantiated”.

A dynamic page will be aware of its particular circumstance, and will thus need to be instantiated (or have some complex logic to handle state.) So, for example, a dynamic home page object might be aware of whether a user is logged in or not, and know whether the login (or logout) button should be present.

Practically, the easiest way to do this is to instantiate a page and set the state. I don’t like to do this on the principal that test code shouldn’t need tested. If a page is just a set of accessors for element locators (and perhaps some helper methods to fill out forms, etc.), then not much can go wrong, and thus need tested.

There are two problems with this.

1. You have no way to validate the page. It will still fail (if an element isn’t present for instance) but then you’re digging around your code to find out why your test failed. The easy solution is to sprinkle your page objects with asserts. And that means letting it know about your test framework either by passing the test object to the page or having the page extend your test object. (or building an observer/notifier relationship between your test framework & page object which is again more complexity than I want.)

2. You end up reproducing business logic in the test. This is wasted effort but also error prone. I often make assumptions about functionality while testing that later prove mistaken (or get overridden because my QA tests aren’t treated as a functional spec by developers or business.)

Both of these issues become more apparent when you extend beyond the single page metaphor and start testing complex situations (like account registration and login.)

Previously, I’d liked to have simple (dumb and static) page objects, that described the page. Because philosophically, a page doesn’t know if a user is logged in. That’s application state.

But issues like whether the login link is displayed, or more significantly, if there are dynamic locators (such as a list of cart items that are identified by the order they are displayed) you end up needing state logic for the page to be valuable, or you end up building logic into your tests, and your page objects start looking like nothing better than a GUI map (which is still a decent abstraction in itself) but I’m also thinking about helper navigation objects that know how to do things like login, register, or checkout to help with setup.

A decent compromise is to have dumb page objects, but a smart “site” object that does know about assertions. Your test can then include a site object that does know how to validate (that you’re on the right page, for instance) and your page objects can still be easy to maintain.

I’ve also tried creating a site object that has page objects and helper objects to navigate and check state. The helper objects are then selenium and test aware, and the page objects are just dumb locators.

The issue of extracting the mechanism of automation (like webdriver) or the issue of locators is another topic. Although I’ve tended to make dumb page objects that have public static strings as locators, rather than locators that know how to be manipulated. Another question is whether you want getters and setters, and in some instances (with dynamically identified locators) this is necessary.

I spent some time in the past creating page elements for buttons, links, textareas, etc. that implement “clickable”, “editable”, etc. interfaces, but decided against that for general use, because Selenium (or whatever framework is used) is the default API, and I don’t want to invalidate someone else’s knowledge with something like that. Webdriver actually does this to a significant degree, but is too awkward for my taste due to it’s generality.

Back to the issue of smart or dumb page objects, I guess I haven’t really answered the question. I’ve really only outlined what I’ve done and a few arguments and clarifications. I have found that using a dynamic language like PHP or Ruby that it is easier to have dynamic page objects, but then it requires getters and setters in order to easily determine IDE hinting, which is something that is inherently more difficult with dynamic languages. And an important part of my goal of an abstraction layer around automated tests is to make the API discoverable. That’s the key to getting users to use it, or else they will go reimplementing stuff in their own tests and you have a maintenance nightmare.

Follow fijiaaron

In 2005 I quit my job and moved to Fiji, then sailed to Australia. But I came back for the girl I left behind.

We got married & moved to Ecuador. We have 4 young children, and recently spent 6 months traveling around the USA in a motorhome. We're currently in Southern California enjoying the beach and plotting our next adventure.

One Shore is my software QA services company. I specialize in test automation with open source tools, implementing continuous integration and delivery, and setting up cloud test environments. I love working with distributed teams.