Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Lessons Learned: Migrating Tests to Selenium v2


Published on

Talk from Selenium San Francisco Meetup on 09/20/2011 hosted at Hearsay Social

Published in: Technology
  • Login to see the comments

Lessons Learned: Migrating Tests to Selenium v2

  1. 1. Lessons Learned:<br />Migrating Tests To Selenium v2<br />September 20, 2011<br />Roger Hu (<br />
  2. 2. Hearsay Social<br />“If 2011 is the year of social media for business, Hearsay [Social] may have some say about it.”<br /><ul><li>Enterprise leader in social media management for regulated B2C organizations
  3. 3. Enables reps to compliantly capitalize on LinkedIn, Twitter, and Facebook
  4. 4. Backed by Sequoia, NEA, Steve Chen, FB execs
  5. 5. Visionary founders and management team from GOOG, SFDC, MSFT, AMZN</li></li></ul><li>Overview of Talk<br />Reasons to Switch<br />Overview of Selenium v2<br />Issues/Workarounds in Selenium v2 <br />Q/A<br />
  6. 6. Reasons to Switch<br />Selenium v2 more closely approximates the user experience.<br />Internet Explorer (IE7/IE8) especially runs faster with Selenium v2 (> 20%?)<br />Easier to write tests. WebDriver reflects how other JavaScript frameworks work.<br />
  7. 7. Selenium v2 Approach<br />Example:<br />driver = webdriver.Firefox()<br />driver.find_element_by_xpath(“//a[text()=‘Create New Ad’”).click()<br />driver.find_element_by_id(“ads_headline”).send_keys(“Selenium Testers Wanted”)<br />Selenium server launches without needing proxy-based approach. <br />Browser driver generates native keyboard/mouse clicks to more closely simulate user behavior.<br />WebDriver API (REST-based) simpler. <br />Browser-specific driver<br />i.e.: IEDriver.dll (IE), webdriver.xpi (Firefox)<br />+<br />WebDriver API<br />
  8. 8. Complexities of Moving to Selenium v2<br />Your tests have to be rewritten to leverage the WebDriver API. <br />Record/playback less useful option? (Selenium IDE plug-in for Firefox)<br />Synchronization issues: implement more implicit/explicit wait conditions (Selenium v2 sometimes acts like an impatient user) <br />Hidden/non-visible elements can no longer be clicked.<br />Specific WebDriverextension for each browser.<br />Cross-browser issues with mouse click/keyboard events.<br />CSS3 selectors now more dependent on the browser (unlike Selenium v1).<br />Not all WebDriver extensions are fully baked (i.e. Chrome, Android, iPhone)<br />Keeping up with the release cycles.<br />Release Candidates: toggle()/select() removed from API.<br />We do a lot of pip –U selenium. Make sure you’re using the latest version of your preferred language binding!<br />Documentation is sparse, and hard to debug without digging through Selenium source code (Java, C++, and JavaScript).<br />
  9. 9. Visibility Matters<br />i.e. driver.find_element_by_id(“cms_toolbar_icon”).click()<br />The X/Y coordinates of the element location are used to determine where to click.<br />Hidden elements can no longer be acted upon until they are visible.<br />The element gets focused and clicked. Some quirky issues with elements at top or bottom of the screen exist.<br />CSS z-index takes precedence now; the top-most element will be the one that receives the mouse event. <br />If you use any type of debug overlay tool (i.eDjango Debug Toolbar, Rails Footnotes, etc.) disable them before running your Selenium tests! <br />
  10. 10. Using Cookies<br />In the Django Debug Toolbar case, we can set a cookie called ‘djdt’ to disable the overlay.<br /><ul><li>You have to open a connection to the page before you can set the cookie. Exceptions usually get thrown otherwise.
  11. 11. Contrary to the documentation, setting cookies actually requires passing in a dictionary of name, value, and secure parameters.</li></ul>driver.add_cookie({"name" : "djdt",<br /> "value" : "true",<br /> "path" : "/",<br /> "secure" : False})<br />(name, value, secure parameters required)<br /><ul><li>To set cookies in IE, Protected Mode must be disabled for all zones. IE8 doesn’t appear to throw any exceptions if cookies can’t be set.</li></li></ul><li>Implicit vs. Explicit Waits<br />Implicit Waits vs. Explicit<br />Implicit waits just need to be set once during setup(server-side polling)<br />Use implicit waits for most page loads, assuming you have a unique DOM element present.<br />Implicit waits complete once element present in DOM (click and other mouse events require visible elements).<br />Explicit Waits<br />Remember wait_for_page_load() and wait_for_condition() in Selenium v1?<br />Use explicit waits for all other cases (i.e. popup dialogs that are already rendered in the DOM but aren’t shown, waiting for a DOM element to disappear, etc.):<br />Use WebDriverWait’s anytime you need to avoid JS/database race conditions (client-side polling)<br />Selenium v2.6.0+: ExpectedConditionsclass to handle often-used cases (clickable elements, text present, etc.)<br />driver.implicitly_wait(30) (sets timeout for finding elements)<br />from import WebDriverWait<br />WebDriverWait(driver, timeout=30).until(lambda driver: driver.find_element_by_css_selector("div.popup.contentul.tabs").is_displayed)) <br />driver.find_element_by_id(“myelement”)<br />driver.find_element_by_css_selector(“#myelement”)<br />driver.find_element_by_xpath(“//div[@id=‘myelement’]”)<br />WebDriverWait(driver, timeout=30).until(lambda x: driver.execute_script(“return === 0”) (wait for Ajax calls to complete)<br />
  12. 12. Demo<br />So how does this implicit/explicit wait stuff work?<br />Let’s play Hearsay Social Says... (Selenium v2 source code posted on the site)<br />def play_level():<br />driver.find_element_by_name("b").click()<br />WebDriverWait(driver, timeout=10).until(lambda driver: driver.find_element_by_name("s").get_attribute("value") == "Player's Turn")<br />pcclicks = driver.execute_script("return pcclicks;")<br /> for pcclick in pcclicks[1:]:<br />ele = "pl%s" % pcclick<br />driver.find_element_by_name(ele).click()<br />driver.find_element_by_name("b").click()<br /> # Alert box shows up. Let's dismiss it.<br />driver.switch_to_alert()<br /> Alert(driver).accept()<br />for i in xrange(20):<br />play_level()<br />
  13. 13. Native vs. Synthetic Events<br />Selenium v1 relied entirely on generating events through JavaScript, while Selenium v2 tries to do it through the operating system.<br />Selecting a dropdown:<br />driver.find_element_by_xpath("//select[@id=‘myselect']/option[text()=‘Seattle']").select() (deprecated)<br />driver.find_elements_by_css_selector("#myselect option")[2].click() # IE7/IE8 won’t click (JS issue)<br />from selenium.webdriver.common.keys import Keys<br />driver.find_element_by_css_selector("#myselect").send_keys(Keys.DOWN) (IE7/IE8 have different behavior for disabled elements)<br />One workaround:<br />driver.execute_script(“$(‘#myselect option’][2].change()’);”) (use jQuery to trigger select-box changes)<br />You can always bypass some cross-browser issues related to native events by reverting to JavaScript-based events, though it’s not ideal.<br /><select id=“myselect”><br /> <option value="1">Seattle</option> <br /> <option value="2“ disabled=disabled>Boston</option> <br /> <option value=”3”>San Francisco</option><br /> <option value=“4">Washington D.C.</option> <br /></select> <br />
  14. 14. Hover states, drag-and-drop, motion-based gestures, HTML5….<br />Want more complex sequences of keyboard/mouse actions (i.e. right clicks, double clicks, drag/drop)? Use the ActionChains class.<br />Creating hover states: also done through ActionChains class. <br />Remember, the elements still have to be visible for them to be chained!<br />Many advanced user interactions still somewhat experimental, so expect issues.<br />from selenium.webdriver import ActionChains<br />driver.get(‘’)<br />menu_mlb= driver.find_element_by_id("menu-mlb")<br />chain = ActionChains(driver)<br />chain.move_to_element(menu_mlb).perform()<br />chain.move_to_element(menu_mlb).click(scores).perform() (scores is not visible until MLB is selected)<br />scores = driver.find_elements_by_css_selector("#menu-mlb div.mod-content ul li")[1] <br /><br />
  15. 15. <ul><li>Earlier blog postsabout Selenium encourage using CSS selectors instead of XPath: </li></ul>div:contains(“Click here”)vs. //div[text()=“Click here”)<br />Matching by inner text? You still may need to use XPath.<br />CSS selectors supported in Selenium v1 are not standard (i.e. contains())<br />Selenium v2 relies on document.querySelector() for modern browsers (IE8+, Firefox 3.5+). <br />If document.querySelector() isn’t supported, the Sizzle CSS engine is used.<br />Even if you’re using a CSS3 selector, check whether it’s supported in IE.<br />driver.find_element_by_css_selector(“#ad-summary:last-child") (breaks in IE7)<br />driver.find_element_by_css_selector(“#ad-summary.last") (workaround: explicitly define the <br />last element when rendering the HTML)<br />CSS Selectors in Selenium v2<br />
  16. 16. Other Tips & Tricks…<br />Use Firebug with Selenium v2.<br />Create a profile and installing the extension:<br />firefox -ProfileManager --no-remote (launch profile manager and install Firebug extension)<br />Specify profile directory:<br /> profile = FirefoxProfile(profile_directory=“/home/user/.mozilla/firefox/60f7of9x.selenium”)<br />driver = webdriver.Firefox(firefox_profile=profile)<br />Test on local browsers first, use SSH reverse tunneling when testing on remote devservers:<br />Install Selenium server on host machine:<br />java –jar selenium-server.jar (default port 4444)<br />Create a SSH tunnel into remote machine: <br />ssh-nNT -R 9999:<IP address of server>:4444 connect to port 9999)<br />Login to remote machine and connect via webdriver.Remote()<br />driver = webdriver.Remote(command_executor=http://localhost:9999/wd/hub)<br />Using SauceLabs? <br />Make sure your max-duration: option is set if your test runs exceed 30 mins. <br />Can’t keep up with the Selenium v2 release cycles? Fix your version with selenium-version: option.<br />Use exit signals handlers to issue driver.quit() commands to see your test results sooner.<br />
  17. 17. Summary<br />Selenium v2 gets closer to simulating the user experience with an entirely new architecture (WebDriver API + browser plug-in/extension).<br />Your tests may start failing on clicking on hidden/non-visible elements, so disable your debug overlays and be aware of CSS z-index issues.<br />Bugs/issues with generating events still persist, and you may encounter many browser quirks (i.e. dropdown boxes).<br />WebDriver may run faster, though you may need to add more synchronization checkpoints with implicit/explicit waits.<br />When using CSS selectors, use the ones supported across all browsers (especially IE). <br />
  18. 18. Q/A<br />
  19. 19. Questions/Comments?<br />