The task was to go to various woot web sites and to read the product name and price of the offer of the day.
I wrote a little bit of Selenium code and thought I'd post it here in case any of it is useful to anyone.
I got the job - so it can't be too bad.
First up I defined an interface to represent a woot page:
package uk.co.doogle;
import com.thoughtworks.selenium.Selenium;
/**
* This interface defines the methods we must implement for classes
* of type Woot. Woot web sites have one item for sale every 24 hours.
* @author Tony
*/
public interface Woot {
/**
* Defines the interface of the method we use to get the price
* of the item for sale on a Woot website
* @param selenium the selenium object we pass in which is used to interact
* with the browser/web page
* @return String representation of the price of the item for sale
*/
public String getPrice(Selenium selenium);
/**
* Defines the interface of the method we use to get the product name
* of the item for sale on a Woot website
* @param selenium the selenium object we pass in which is used to interact
* with the browser/web page
* @return String representation of the product name of the item for sale
*/
public String getProductName(Selenium selenium);
}
Then I implemented this interface a few times to represent the actual behaviour of the various woot pages - here for example if the winewoot page:
public class WineWoot extends BaseWoot {
 /**
  * Constructor
  * @param url pass in the url of the web site
  */
 public WineWoot(String url) {
  super(url);
 }
 /**
  * Implementation of the method to get the price of the object for sale on 
  * the Woot web site.
  */
 public String getPrice(Selenium selenium) {
  //if you need to update the xpath to the piece of text of interest - use xpather firefox plugin
  String xPath = "//html/body/header/nav/ul/li[8]/section/div/a/div[3]/span";
  selenium.waitForCondition("selenium.isElementPresent(\"xpath=" + xPath + "\");", "12000");
  return selenium.getText(xPath) + " ";
 }
 /**
  * Implementation of the method to get the product name of the item for sale 
  * on the Woot web site
  * 
  */
 public String getProductName(Selenium selenium) {
  //if you need to update the xpath to the piece of text of interest - use xpather firefox plugin
  String xPath = "//html/body/header/nav/ul/li[8]/section/div/a/div[2]";
  selenium.waitForCondition("selenium.isElementPresent(\"xpath=" + xPath + "\");", "12000"); 
  return selenium.getText(xPath) + " ";
 } 
}
Note - back then I used the xPather plugin - this doesn't work for recent versions of firefox, so now I use firebug.
Then I wrote the actual 'test':
package uk.co.doogle;
import com.thoughtworks.selenium.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
/**
 * This class is where we define tests of the Woot web sites
 * @author Tony
 *
 */
public class TestWoots extends SeleneseTestCase {
 /**
  * Outputstream for our results file
  */
 private BufferedWriter out;
 /**
  * Our list of Woot web sites we want to test
  */
 private List<BaseWoot> sites = new ArrayList<BaseWoot>();
 /**
  * This is where we do any set up needed before our test(s) run.
  * Here we add the list of Woot web sites we want to test and we create an 
  * output stream ready to write results to file
  */
 public void setUp() throws Exception {
  sites.add(new BaseWoot("http://www.woot.com/"));
  sites.add(new ShirtWoot("http://shirt.woot.com/"));
  sites.add(new WineWoot("http://wine.woot.com/"));
  try {
   //let's append to our file...
   FileWriter fstream = new FileWriter("out.csv", true);
         out = new BufferedWriter(fstream);
         out.write("Site, Product Name, Product Price");
         out.newLine();
  } catch (Exception e) {
   System.err.println("Error creating a file to write our results to: " + e.getMessage());
  }
 }
 /**
  * Tests getting the item name and price for the item for sale on each Woot web site we test.  We see the results of the test 
  * in std out in the form of a table and we also write the results to a csv file.  
  * If there are any errors getting the information, this is displayed instead.  
  * 
  * How to run me: open command prompt and from the directory where our selenium server is 
  * located type: java -jar selenium-server-standalone-2.0b3.jar (or equivalent) and wait for the server to start up. 
  * Then just run this unit test.
  */
 public void testGetItemsAndPrices() throws Exception {
  //for each Woot site in our list of sites we want to test
  for (BaseWoot woot : sites) {
   //let's put this in a try catch block as we want to try ALL the sites - some may be down or slow...
   try {
    selenium = new DefaultSelenium("localhost", 4444, "*firefox", woot.getUrl());
    selenium.start();
    selenium.open("/");
    selenium.waitForPageToLoad("50000");
    //add a new row for our table to std out
    System.out.println();
    //print out the information we need - the site, the title of the item for sale and the price
    String siteUrl =  woot.getUrl();
    String productName = woot.getProductName(selenium);
    String productPrice = woot.getPrice(selenium);
    //sometimes there are commas which mess up our csv file - so
    //we substitute with ;
    productName = productName.replace(",", ";");
    System.out.print("website: " + siteUrl + " ");
    System.out.print("product name: " + productName);
    System.out.print("price: " +   productPrice);
    out.write(siteUrl + ", " + productName + ", " + productPrice);
    out.newLine();
   } catch (Exception ex) {
    //here may may see that the web site under test has changed and the xpath to the price or product name may need to 
    //be changed in the Woot class
    System.out.print("problem getting the data for: " +  woot.getUrl()+ " " + ex.getMessage() + " ");
   } finally {
    selenium.stop();
   }
  }
 }
 /**
  * Any tear-down we need to do to cleanup after our test(s).
  * Here we just stop selenium and close the output stream
  */
 public void tearDown() throws Exception {
  selenium.stop();
  out.close();
 }
}
I know this code worked for a couple of years, and I have made some minor changes to get it to work with the current woot.com web sites - all I had to do was get the latest selenium-server-standalone.jar for it to work with the latest firefox and also to update the xpaths to the price and product name information.  That would be a good improvement to the code - to make it data driven - such that we could just update the xpaths in a config file rather than changing the hard-coded ones I have used here.  That was the only feedback from the client actually.
Anyway - hope you find it useful - and if you need expert automation engineers get in touch with Doogle!
 
Interesting piece of code could you help me installing some html code in my blog? i could pay you..
ReplyDeleteLynda
Hi - glad you found it interesting! Get in touch via my web site with more details about what you need to do (www.doogleonline.co.uk) and I'll see if I can help, Cheers, Tony.
DeleteThis comment has been removed by the author.
ReplyDelete