Approach for Watir-Webdriver coverage on site with many clients

Go To StackoverFlow.com

3

Ok, I need a boost on this thought process - my brain hurts. I'd like to get your feedback on some approaches.

I'll post my questions up front just in case I lose your attention during the description below:

  • Have you scripted a similar product before? How did you approach it?

  • Do any of these approaches stand out as great/terrible for any reason? If so, what?

  • Is there another approach that you would find more appropriate?

There is a workflow that I am testing, for argument's sake we'll call it a shopping cart that consists of various text_fields, radio_buttons and select_lists. One company provides this shopping cart for ~60 clients, and not all of the clients use the same exact forms but the general process is the same. The general idea is the same between clients (same target functionality) and there are subsets of clients with the same exact workflow, but many that are unique. In this scenario, unique may mean that certain fields are not required while they may be for other clients. Or, certain questions/text_fields exist for one client that no others may use at all.

The goal of the script at this point is just to generate an order through the web interface, not to verify each individual step of the process as a 'test'. You'll have to trust me a bit here. There are still plenty of common details to be able to run negative/edge cases with an acceptable level of accuracy.

The approaches that I see so far are:

  1. Using page object pattern, create a "page" file for each client site and use a different page Class depending on which client is being tested. This is tedious, mostly fragile and a lot of work to maintain. However, it would work and I could use the same feature/scenarios for everyone as long as their specific page file was accessible.

  2. Create a method to scrape all of the input elements from the DOM, detect if they are a reserved field that we need to inject specific required input into, or just fill in information to get the order to complete. This does not piggyback on the DB so performance should be better overall.

  3. Hook into the DB, gather all the information required by the specific client used to build their pages, and dynamically build the fields for the order, and answer them accordingly. This sounds great in theory, would require very little if any maintenance. DB scraping is easy, the difficulty building the fields is as yet unknown to me...

Right now I'm using: watir-webdriver cucumber Cheezy's page-object gem sequel

2012-04-05 20:16
by adam reed
If you think there's a blog/article that I should read, or a book that I should buy - please let me know that as well. I realize I can't be the first person considering this decision, and I also don't expect others to do the legwork for me - adam reed 2012-04-05 20:28
How stable are the client configurations and who configures them? For example, will the test maintainer know when the forms/pages change? Do the forms change frequently or do they stay as originally implemented? I am asking to better understand the maintenance required given the different approaches - Justin Ko 2012-04-06 13:57
@JustinKo - the major parts (ordering of pages, questions) should be static enough not to worry about them changing except in extreme cases. Features like availability (a US area map with active state links only on states that are available) will change fairly regularly, but I already have a method to detect these dynamically, or accept user input for the script and proceed/fail based on the location's availability - adam reed 2012-04-06 14:13


3

I would use cheezy's page-object and include every field/question that could be included. then I would overload the default values for each customer including only the fields/questions that they use. Hopefully, I did not oversimplify that.

Update: In the page populator, it will merge whatever you data send (as a hash) with default data. In his default data post, he shows how to use default data. I figure that you can create a class checkout page

 class CheckoutPage
  include PageObject

  text_field(:name, :id => “order_name”)
  text_field(:address, :id => “order_address”)
  text_field(:email, :id => “order_email”)
  select_list(:pay_type, :id => “order_pay_type”)
  button(:place_order, :value => “Place Order”)

  PageObject::PageFactory.routes = {
    :default => [[HomePage, :select_puppy],
                 [DetailsPage, :add_to_cart],
                 [ShoppingCartPage, :continue_to_checkout],
                 [CheckoutPage, :complete_order]]
  }

  def complete_order(data = {})
     data = DEFAULT_DATA.merge(data)
     self.name = data['name']
     self.address = data['address']
     self.email = data['email']
     self.pay_type = data['pay_type']
     place_order
   end
 end

then overload it for specific vendors using the site and each has it's own default data.

class Nordies < CheckoutPage
      DEFAULT_DATA = {
        ‘name’ => ‘cheezy’,
        ‘address’ => ‘123 Main Street’,
        ‘email’ => ‘cheezy@example.com’,
        ‘pay_type’ => ‘Purchase order’
      }

PageObject::PageFactory.routes = {
  :default => [[HomePage, :select_puppy],
               [DetailsPage, :add_to_cart],
               [ShoppingCartPage, :setup_creditcard],
               [CreditCardPage, :continue_to_checkout],
               [CheckoutPage, :complete_order]]
}
end

Then the .complete_order will be different for every vendor.

2012-04-05 20:34
by Dave McNulla
I'm not sure what you mean by overload the default values, but by the rest of your answer it sounds like you'd basically run though an "if fieldone.exists? { fill it out }" approach? I am attempting to use Cheezy's default data approach two as it has always been great for other projects in the past, with the newer populatepage_with method. I'm not sure technically if that would be appropriate using that approach - adam reed 2012-04-05 20:45
http://rubydoc.info/github/cheezy/page-object/master/frame - Dave McNulla 2012-04-05 20:52
Right, I'm using his gem (and was using his page object approach before it was a gem), but I'm not sure what you meant by overload the values. I think we're being a bit too succinct - adam reed 2012-04-05 20:55
That comment was an accident. I decided a comment was too limiting to say anything useful so I updated my answer - Dave McNulla 2012-04-05 21:02
Interesting - so default data would be the subset that each client has (if any), and then the Client class < CheckoutPage could not just be different default data values, but possibly contain additional Hash items? Along with single form data like this, there are slight page flow differences (does the shipping address page come before the review cart page, etc) that I don't think it could handle, but it's a good start - adam reed 2012-04-05 21:14
Now my brain hurts. Let me think some more - Dave McNulla 2012-04-05 21:56
Adam, did you ever look at the PageFactor::Routes that I added? That may help you too - Dave McNulla 2012-04-06 21:50
Yes, I liked the idea when I read it on Cheezy's site but hadn't thought it too far through yet.. I could define different routes for each company since they all have the same pages, just in a different order. I dig - adam reed 2012-04-07 02:01
I've accepted this answer - I think I'm going to end up having many includes (one per page per process for each client), however, I will be able to use PageFactory routes in order to parameterize it in the steps and save time/code. (pseudo: case "client"; when "dave'stestingshop" route == "dave"). It's definitely limited by the project, not the test. Thanks - adam reed 2012-04-10 18:27
Ads