London Selenium Users Event #4

Posted: March 10th, 2011 | Author: Dave | Filed under: Events | 2 Comments »

In a couple of weeks the 4th event of the London Selenium users meetup takes place. This time it will be hosted by Thoughtworks, and has a loose theme of extending on top of Selenium. I’m pleased to announce the following speakers, in addition to a talk from Google on mobile testing with Selenium.

Andy Kemp – Andy has been working in software for 15 years. The last 6 have been at ThoughtWorks where he has worked as a tester and project manager across London, San Francisco and Sydney. His latest role is Product Manager for Twist. He has recently started blogging at http://kyndainverse.com

Samit Badle – Samit is a Selenium Committer and author of several Selenium IDE plugins. He is a Oracle Certified Java Programmer, Microsoft Certified Solution Developer and is also a ISEB certified tester.

Andy Smith – Andy has been building websites for over 10 years and runs CanvasDemos.com, a repository for applications which use the HTML5 Canvas element.

The event is currently full, but join the waiting list if you’re interested in attending and if someone changes their RSVP you will be able to take their place.


Selenium Conference 2011 – Survey

Posted: November 30th, 2010 | Author: Dave | Filed under: Events | Tags: , | No Comments »

The first ever Selenium is currently being planned for sometime in April next year. Get involved by responding to this short survey. Your responses will be used to help plan the conference.


Videos now online for ‘Advanced Test Automation with Firefox’

Posted: November 19th, 2010 | Author: Dave | Filed under: Events | Tags: , , , , , | No Comments »

The videos from the third London Selenium users event are now available on the London Selenium YouTube channel: http://www.youtube.com/user/londonselenium/


Meetup.com Attendance Lists

Posted: November 8th, 2010 | Author: Dave | Filed under: Examples | Tags: , , , , | No Comments »

For the recent London Selenium Users Meetup Event I was asked if I could provide the attendance list in a suitable format for creating labels for the guests when they arrive. Given the short timeframe I did this simply by highlighting the names on meetup.com, copying them, and pasting them into a simple text editor. I then quickly cleaned this up before sending the list on. Within a short while the list was out of date due to some members dropping out.

It did occur to me at the time that I could write a simple Selenium script, but I didn’t want to delay providing the list. Well I’ve now had some time to revisit this, and hopefully for the next meetup event I’ll be more prepared. The following script should work on both upcoming and past events. It doesn’t support waiting lists, and may have problems if meetup.com truncates lists after a certain number. I may revisit these items once I’ve scheduled the next event.

Meetup.java

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
 
import java.util.ArrayList;
import java.util.List;
 
public class Meetup {
 
    HtmlUnitDriver driver;
 
    String meetup = "seleniumlondon"; //meetup name from URL
    String event = "14712022"; //event ID from URL
 
    @BeforeTest
    public void startDriver() {
        driver = new HtmlUnitDriver();
    }
 
    @AfterTest
    public void stopDriver() {
        driver.close();
    }
 
    @Test
    public void listResponses() {
 
        //open the event page
        driver.get("http://www.meetup.com/" + meetup + "/calendar/" + event + "/");
 
        if (driver.findElement(By.xpath("id('C_document')/descendant::dl[@class='stats'][2]/dt")).getText().equals("Who’s coming?")) {
            //this event has not yet occurred
            listMembers("id('C_document')//li[div[@class='D_attendeeHeader D_yes']]//li[starts-with(@id, 'member_')]", "Yes");
            listMembers("id('C_document')//li[div[@class='D_attendeeHeader D_maybe']]//li[starts-with(@id, 'member_')]", "Maybe");
            listMembers("id('C_document')//li[div[@class='D_attendeeHeader D_no']]//li[starts-with(@id, 'member_')]", "No");
        } else {
            //this event is in the past
            listMembers("id('C_document')//li[starts-with(@id, 'member_')]", "Attended");
        }
    }
 
    public void listMembers(String xpath, String label) {
 
        //get a list of all members that have responded or attended
        List<WebElement> memberElements = driver.findElements(By.xpath(xpath));
 
        int guestTotal = 0; //set guest total to zero
        List<Member> members = new ArrayList<Member>(); //create a list to store our members
        for (WebElement member : memberElements) {
            String name = member.findElement(By.className("D_name")).getText(); //member name
 
            int guests = 0; //set member's guests to zero
 
            //get the number of guests for this member
            try {
                //upcoming events use a different class for the guest count as past events
                String guestsTemp = member.findElement(By.className("guests")).getText();
                guests = new Integer(guestsTemp.substring(guestsTemp.indexOf("+")+1, guestsTemp.indexOf(" ")));
            } catch (NoSuchElementException e) { }
 
            try {
                String guestsTemp = member.findElement(By.className("D_guests")).getText();
                //past events use a different format for the guest count
                guests = new Integer(guestsTemp.substring(guestsTemp.indexOf("+")+1, guestsTemp.indexOf(")")));
            } catch (NoSuchElementException e) { }
 
            guestTotal = guestTotal + guests; //update the total number of guests for this event
            members.add(new Member(name, guests)); //add the current member to our list
        }
 
        //output a label for this list including total member and guest counts
        System.out.println("\n" + members.size() + " " + label + getGuestSuffix(guestTotal));
 
        for (int i=0; i<members.size(); i++) {
            //output details for each member
            System.out.println(i+1 + ". " + members.get(i).name + getGuestSuffix(members.get(i).guests));
        }
    }
 
    public String getGuestSuffix(int guests) {
        //return a suffix to indicate the number of guests
        if (guests > 0) {
            return " (+" + guests + " guest" + (guests > 1 ? "s" : "") + ")";
        } else {
            return "";
        }
    }
 
    //inner class for members
    public class Member {
 
        String name;
        int guests;
 
        public Member(String name, int guests) {
            this.name = name;
            this.guests = guests;
        }
 
    }
 
}

Cheesecake

Posted: November 7th, 2010 | Author: Dave | Filed under: Examples | Tags: , , , , | 2 Comments »

Here’s another one of my odd Selenium examples! Last month I finally got to eat at a ‘Cheesecake Factory’ restaurant, after first hearing about them a few years back from an American friend. There’s an overwhelming choice of 30+ cheesecakes to choose from, and I’m really not good at making decisions when there’s so much choice. I decided to go with ‘The Original’, and that every subsequent visit to the chain I would work my way down the menu, knowing I’d probably never get through all of them in my lifetime!

So as I’m in California right now, I remembered my experience, and decided to check out the full menu from the restaurant so that I could add it to Evernote and keep track of my progress. Unfortunately I wasn’t able to do a nice copy+paste from the site, so – as usual – I wrote a Selenium script to list all the cheesecakes. For a change this script uses the HtmlUnitDriver, however you can easily swap in one of the other browser drivers.

CheesecakeFactory.java

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
 
import java.util.List;
 
public class CheesecakeFactory {
 
    HtmlUnitDriver driver;
 
    @BeforeTest
    public void startDriver() {
        driver = new HtmlUnitDriver();
    }
 
    @AfterTest
    public void stopDriver() {
        driver.close();
    }
 
    @Test
    public void listCheesecakes() {
        driver.get("http://www.thecheesecakefactory.com/");
        driver.findElement(By.linkText("Menu")).click();
        driver.findElement(By.linkText("Cheesecake")).click();
        List<WebElement> cheesecakes = driver.findElements(By.xpath("id('leftNav_levelTwo')//li"));
 
        System.out.println(cheesecakes.size() + " cheesecakes:");
        for (int i=0; i<cheesecakes.size(); i++) {
            System.out.println(i+1 + ". " + cheesecakes.get(i).getText());
        }
    }
 
}

Output

34 cheesecakes:
1. The Original
2. Fresh Strawberry
3. Reeses Peanut Butter Chocolate Cake Cheesecake
4. 30th Anniversary Chocolate Cake Cheesecake
5. White Chocolate Raspberry Truffle®
6. Ultimate Red Velvet Cake Cheesecake™
7. Godiva® Chocolate Cheesecake
8. Fresh Banana Cream Cheesecake
9. Adam's Peanut Butter Cup Fudge Ripple
10. White Chocolate Caramel Macadamia Nut Cheesecake
11. Lemon Raspberry Cream Cheesecake
12. Dulce de Leche Caramel Cheesecake
13. Chocolate Coconut Cream Cheesecake
14. Tiramisu Cheesecake
15. Chocolate Mousse Cheesecake
16. Vanilla Bean Cheesecake
17. Chocolate Tuxedo Cream™ Cheesecake
18. Kahlua® Cocoa Coffee Cheesecake
19. Pineapple Upside-Down Cheesecake
20. Chocolate Raspberry Truffle®
21. Dutch Apple Caramel Struesel
22. Chocolate Chip Cookie - Dough Cheesecake
23. Wild Blueberry White Chocolate Cheesecake™
24. Low Carb Cheesecake
25. Low Carb Cheesecake with Strawberries
26. Key Lime Cheesecake
27. Caramel Pecan Turtle Cheesecake
28. Brownie Sundae Cheesecake
29. Snickers® Bar Chunks and Cheesecake
30. Craig's Crazy Carrot Cake Cheesecake
31. Oreo® Cheesecake
32. Cherry Cheesecake
33. Pumpkin Cheesecake
34. Pumpkin Pecan Cheesecake

Hmmm… Maybe I should get the Caltrain into San Francisco and make it 2 down, 32 to go!


How Mozilla Uses Selenium

Posted: November 5th, 2010 | Author: Dave | Filed under: Events | Tags: , , , , | 1 Comment »

London Selenium Meetup Event #3

Posted: November 5th, 2010 | Author: Dave | Filed under: Events | Tags: , , , , , , | No Comments »

This week saw the third London Selenium Users Meetup event, with presentations from Mozilla and an update from Simon Stewart on the progress of Selenium 2. You can read my full write-up of the event on my personal blog.


New London Users Event: Advanced Test Automation with Firefox

Posted: September 24th, 2010 | Author: Dave | Filed under: Events | Tags: , , , , , | No Comments »

Although it’s been scheduled for a while, the next London Selenium Users meetup event has now been officially announced. As before, Google will be generously hosting the event, which this time is Firefox flavoured! There will be four presentations, mostly by folks from Mozilla, but also an update from Simon Stewart on the progress of Selenium 2. Head over to the event page on meetup.com for all the latest details.


Checking Wedding Gifts with Selenium

Posted: August 23rd, 2010 | Author: Dave | Filed under: Examples | Tags: , , , , | No Comments »

Admittedly this one is unlikely to be useful to many, but it could still serve as a useful example for Selenium 2. Also, I haven’t posted an example since alpha 5 was released.

I’m getting married in a few short weeks, and our gift list has now opened for any guests that would like to buy us something for the occasion. We debated over having a list in the first place, but in the end decided that it was probably for the best. One of our hesitations was that we didn’t want to know what people had bought for us before the day, and having an online gift list makes it possible to ‘spoil’ the surprise.

With the list only having been open a couple of days, the temptation was already pretty difficult to resist and we decided that it was okay to see what has been bought just so long as we don’t find out who’s bought what. Unfortunately this isn’t easy on the site as they’re listed together, so I was sneakily able to construct an XPath that extracted the necessary information. I’ve now combined into a Selenium 2 example using Java, which can be found below.

GiftList.java

package giftlist;
 
import java.util.List;
import java.util.concurrent.TimeUnit;
 
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
 
public class GiftList {
 
	private static WebDriver driver;
	private static final String GIFT_LIST_NUMBER = "123546";
	private static final String GIFT_LIST_PASSWORD = "password";
 
	public static void main(String [ ] args) {
		//open browser
		driver = new FirefoxDriver();
 
		//set implicit wait
		driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
 
		//login
		driver.get("https://www.johnlewisgiftlist.com/");
		driver.findElement(By.linkText("Manage your list")).click();
		driver.findElement(By.name("giftListNumber")).sendKeys(GIFT_LIST_NUMBER);
		driver.findElement(By.name("listPassword")).sendKeys(GIFT_LIST_PASSWORD);
		driver.findElement(By.linkText("Display List")).click();
 
		//get purchased items
		driver.findElement(By.linkText("Gifts purchased")).click();
		driver.findElement(By.xpath("//h1[text()='Gifts purchased by guests']"));
		List<WebElement> purchasedItems = driver.findElements(By.xpath("//tr[td[2] and @class='item']"));
 
		//output purchased items
		for (WebElement item : purchasedItems) {
			System.out.println(item.findElement(By.xpath("/td[1]")).getText());
		}
 
		//log out
		driver.findElement(By.linkText("Log out")).click();
 
		//close browser
		driver.close();
	}
 
}

Proposal for new Selenium Q&A site

Posted: July 8th, 2010 | Author: Dave | Filed under: Proposals | Tags: , , , | 3 Comments »

If you’re not already aware of the dedicated Selenium Q&A site that I have proposed, then it’s definitely worth checking it out. If you’re interested in supporting the proposal, and helping it to reach beta then please commit. By committing you are stating that you are prepared to both ask and answer questions on the proposed site.

So why does Selenium need a new site for Q&A?

Well, first let me give you some history of the official Selenium forums. When I first started to get involved in the Selenium community there was the Clearspace forums, which provided a good structure, a pretty good interface, and a basic reward system. The main problems I had with Clearspace was searching the content, identifying unanswered questions, and the alarming regularity of certain basic (but very suitable) questions. Another issue turned out to be spam, which I believe was the main reason the content was migrated – after much discussion – to Google Groups.

Read the rest of this entry »