(over 90s) • Ignore Open and WaitForPageToLoad failures • Generate application states with test handles • Wait for the right events (never ever use static pauses) • Don't use verifications Selenium 2 tips • Implicit waits • Avoid using complex locators Sauce tips • Report pass/fail status automatically • Use the new Sauce Connect
just call self.click or self.type instead of self.selenium.type def __getattr__(self, name): if hasattr(self, 'selenium'): return getattr(self.selenium, name) raise AttributeError(name) # Ignore open commands that fail (same needs to be don for wait_for_page_to_load) def open(self, url, ignoreResponseCode=True): try: self.selenium.open(url, ignoreResponseCode) except Exception, e: print "Open failed on %s. Exception: %s" % (url, str(e)) pass #sometimes open appears to work fine but flakes out. ignore those # Report pass/fail status to Sauce Labs def tearDown(self): passed = {'passed': self._exc_info() == (None, None, None)} self.set_context("sauce: job-info=%s" % json.dumps(passed)) self.stop() https://gist.github.com/1107711
== "logged in as " + username don't do: selenium.open("/login") selenium.type("username", "santi") selenium.type("password", "bleh") selenium.click("submit") selenium.wait_for_page_to_load(90000) do: magic_login("santi") Generate app states using test handles
tests are better • Testing for multiple conditions in a single workflow gives you hard to read results • Make tests faster with other tricks. Don't cram them in a single workflow.
.delete-links:nth-child(2)") e.click() Use: actions = driver.find_element_by_id("actions") delete_links = actions.find_elements_by_class("delete-links") delete_links[3].click() This keeps logic in your code, not your locators.