Selenium page objects beyond pages like a cart object?

23 Sep

Selenium page objects is a design pattern to help you model test code better. But one doesn’t have to follow the full guidelines of the design pattern.

Some people have used it to model parts of pages as well (headers, footers, navigation, templates, widgets, etc.).  But perhaps it can be useful for more than that, and some people might have already done this or not, as I couldn’t really search anything up or don’t know what/how to search specifically for this. If people have already done this, they haven’t widely publicized it.

What I have found so far is this: https://github.com/cheezy/page-object/wiki/Indexed-Properties

It’s an interesting piece to review. I had this similar thought in mind recently and decided to blog about it:

A shopping cart page doesn’t really do much really. It contains cart items, and offers a visual call to action (click button) that then takes you to checkout. That along with standard site (header/footer/navigation) template actions (login, logout, links to other areas of site).

The core functionality in the shopping cart page really belongs to the cart items and what you can do with them. So in my mind, having the shopping cart page object manipulate cart item actions doesn’t seem quite appropriate for object oriented design.

For example, this would be how you might typically implement the cart page in basic page object model:

cartPage.updateQuantity(cartItemIndex, quantity);
cartPage.removeCartItem(cartItemName);
cartPage.getCartItemName(cartItemId);
//obviously access cart item by index, text string name of item, or by some unique ID

However, perhaps you can extrapolate the cart items outside of the page object to manipulate individually as a collection or set of related WebElements (name, quantity field, remove button, etc.) or for more advanced usage as an encapsulated cart item object model itself.

Both modeling options are presented here below (since I find it hard to list code in a “basic” WordPress blog)

https://gist.github.com/daluu/8e4c43d653c07eb0c57a

I would note that modeling cart items in such a way, while being more object oriented, can make implementing the cart page object (particularly the getCartItems method) and associated procedure to locate and group the related cart item elements together functionally more complicated. Because often, the web application will not have an easily implemented UI that has all the related elements easily related and uniquely identifiable to each other, especially on a cart page with N number of cart items.

Usually that may require sophisticated use of CSS and XPath patterns to locate and relate the set of elements for N cart items on the page. So this this whole approach is not something novice page object model and Selenium users can easily tackle. It takes time and skill to do. But worth trying out.

In the long run, I feel this type of approach is more maintainable, scalable, and makes the tests more readable. It just requires more thought in architectural design and more work upfront to implement. However, the complexity to implement could be reduced if you can get the developers to make the element locator values easily defined w/o resorting to custom CSS and XPath, and make it work for N cart items, and X related cart item elements (e.g. item color, item description, item this, item that, for every cart item)

If you ask me personally which cart item object model I prefer, it is the latter one that resembles a page object rather than the one that is simple a container of WebElements for a cart item.

What are your thoughts on modeling things or objects on a page like a page object. Cart item is the one that tends to come to mind, but there are others, for which they can be thought of as objects but not widgets, nor headers, footers, or navigation for page object modeling. Some other possible examples include a search result, a category listing, etc.

Also, please do inform me if you come across other articles about using page objects for things like cart items, search results, etc. where we’re not working with a page but some other object per se.

Advertisements

9 Responses to “Selenium page objects beyond pages like a cart object?”

  1. Olu October 13, 2014 at 10:31 am #

    I am a subscriber to your blog and i have to say well done for the good job . I am new into automation and POM, just wondering if you can please expatiate a little bit on the getCartItems() method from the CartPage class. in other words, I notice that you assigned the values returned by getCartItems() to an array of the type CartItem. My question is, how are you returning all the possible WebElements for cartItem (labelname, qty, removebutton etc) in the getCartItems() method? guessing the return type for the getCartItems() method is CartItem??

    • autumnator October 14, 2014 at 6:23 am #

      First of all, thanks for following my blog Olu. The exact answer to your question can be considered (your) homework to figure out. I present the basic design/structure for one to then implement the details. Part of this reason is because different (web)sites implement shopping cart (and its related UI element locators) differently. I guess I could present one example implementation specific to some site (maybe in future) but I’m trying to teach a man to fish, not fish for him.

      But what hints/tips I can give you is that if you follow the GitHub gist I posted, essentially getCartItems() method is doing all the hard work of getting all the related WebElements for each cart item then storing or grouping them into a CartItem class object for user to easily manipulate.

      The general trick, assuming that the label name, quantity, remove button/link and other items that logically represent a “cart item” are “related” to each other in some way in the HTML Document Object Model (DOM), is to find that relation. Usually that means they share a common parent that can be identified. The common parent is usually a container that contains everything that represents the cart item. What is nice about WebDriver’s WebElement class is that you can use it to define a root/base/parent element that you can then navigate down into its nested children using some location strategy. So the general technique then is to find the parent (by ID/class/name/XPath/CSS). Then using the parent WebElement, you find each of the child WebElements by same or different location strategy. Usually the shopping cart developers never built it out easily to give each element a nice unique ID, etc. so most likely you may have to resort to advanced XPath or CSS to find each element, but can break apart the XPath/CSS into 2 parts the parent prefix and the other half defining the child element, so the common prefix will be used to find parent, then use the remaining half (w/o prefix) to find each child starting from parent WebElement object. For example:

      parentWebElement = driver.findElement(By.XPath(“//parentXPathPrefixValue”));

      removeBtnElement = parentWebElement.findElement(By.Xpath(“//xpathValue_toRemoveButton_startingFrom_parent_notFromRootOf_DOM_or_HTML”));
      //…repeat for other remaining child elements

      now that’s a simple example. You do have to keep in mind there can be N cart items on shopping cart page. Therefore, the code presented above has to be iterated over, and you normally use the plural version findElements() to get back WebElements (for the parent/base container element) then interate over that to extract the children. Each parent WebElement will have one of each of its children. Done this way you’ll have a set of WebElements for each element group. And done right all that will be grouped nicely in a CartItem object for your user to use so they don’t have to deal with the ugly mess of extracting all those WebElements themselves. You do the ugly work in getCartItems().

      Hope that helps and is enough for you to finish your homework. 😉

      • Olu October 15, 2014 at 11:04 am #

        Thanks for your response. I shall go away and finish my homework. Can I still ask question if stuck with my home work? or better still go over my approach with you offline?

      • autumnator October 15, 2014 at 11:19 pm #

        Yes, you may ask questions. But if you have a lot to ask, better to discuss offline.

      • Olu October 16, 2014 at 9:53 am #

        What will be the best way to chat offline? my email address should be visible to you. can you please email me what the best way to chat with you offline.

      • autumnator October 17, 2014 at 3:39 am #

        I sent you an email.

      • Olu October 21, 2014 at 11:43 am #

        Thanks. I sent you an email as well.

  2. fijiaaron January 13, 2015 at 7:58 pm #

    I’ve gone down the route of modeling domain objects for cleaner test automation, but I’ve found that I often lose sight of what I’m automating.

    The problem is that a CartObject with CartItems is usually not consistent. You might have a mini-cart that users view while navigating, vs a full cart that they see on checkout. And that means implementing equivalent steps in multiple ways.

    Users with different settings (e.g. locale) may have different cart items. And some users may have properties others don’t — that aren’t intrinsic to the cart (e.g. discounts).

    You end up implementing the domain model — often in a better way than the developers — because you understand it better — and aren’t distracted by JDBC, REST, or other technical details.

    But, your interface isn’t a database or a web service — it’s the yucky, brittle, constantly changing HTML and JavaScript and CSS wrapped in a variety of buggy browsers. In other words, it’s not worth the effort.

    The solution is to test that domain logic at the domain layer. And if the same person building (and designing) the system is the one writing the tests — this can be done. Usually it can’t.

    So I find modeling the steps taken is a better approach to automation. You build a test driver with steps. You can build higher level steps above the page level (e.g. login with username and password vs enter username, enter password, click login button, verify logged in) for common preconditions — or verifications ( verify cart contains items, verify discount is applied to items in cart) but you don’t want to rebuild the domain model.

    • autumnator January 13, 2015 at 8:20 pm #

      Thanks for the comment. Good points.

      One issue that comes to my mind that spawned this blog is that sometimes you have a collection of related elements that represent a domain object like cart item, and the way it’s implemented they share common DOM ancestry (some parent locator to navigate the element relative to) to locate by XPath and CSS, but no easy ID/name identifiers. Doing it purely the page object method way, there’s a bit of duplicating code patterns to manipulate element A (remove item link) and element B (unit price), etc. of the cart item elements collection. And one may want to deal with these elements by index vs name/string. It seemed to me at the time, organizing the code collectively into a separate object is a nice way to wrap those code minimizing duplication. Do you have any tips or suggestions for this type of scenario?

      Most examples one finds online for modeling are simple stuff like login scenarios. It would be nice if some folks would blog how they model shopping cart page interaction as page objects, etc. covering things like update quanity, removing items, verifying data in cart page for cart items, checking/applying discounts, etc. checking out. It’s these meaty examples that would much better benefit the test automation community. Simple examples people can easily come up with themselves. These more complex cases require more thought and plannning that Selenium automation novices may overlook. Examples of such can help steer them onto the better ways of modeling.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Pete Zybrick

Bell Labs to Big Data

Seek Nuance

Python, technology, Seattle, careers, life, et cetera...

TELLURIUM

New Era of Test Automation

Der Flounder

Seldom updated, occasionally insightful.

The 4T - Trail, Tram, Trolley, Train

Exploring Portland with the 4T

Midnight Musings

Thoughts on making art

Automation Guide

The More You Learn The More You Play...!

The Performance Engineer

Code.Test.Tune.Optimize.

humblesoftwaredev

Thoughts related to software development

Yi Wang's Tech Notes

A blog ported from http://cxwangyi.blogspot.com

Appium Tutorial

Technical…..Practical…..Theoretically Interesting

LinuxMeerkat

I swear! Meerkats can do Linux

PacketsDropped

Requeuing the packets dropped in my memory.

Two cents of software value

Writing. Training. Consulting.

@akumar overflow

wisdom exceeding 140 chars.

%d bloggers like this: