In the testing community, lots of companies use many different automation tools. It saves a lot of trouble going through repetitive tasks that the computer is quite capable of doing by itself. At Testuff, we don’t try to compete with those tools. They’ve been around for a while, they do a pretty good job, and trying to beat them at their own game is not what we’re after. Nevertheless, we do our best to integrate with as many automation tools as we can (as we do with bug trackers). The only problem so far is that they can’t do your dishes (yet).
I ended up playing with Selenium recently, when we created a Selenium Extension which integrates with Testuff. It got me thinking: Wouldn’t it be useful (and cool) to use those test automation tools to help me keep up with stuff on my personal life as well? How about checking my bank balance, and sending an email with the latest transactions every day? What about the mobile or home phone bill? Track electricity usage? The possibilities are endless.
Many companies nowadays offer web-based access to your own information, from banks to utility companies, mobile phone operators and so on. However, logging in every time, just to check your balance can be tedious.
I’m sure many of our customers are more experienced Selenium users than we are, but I still wanted to give a few hints about making selenium a little more tedious-task-friendly. One of the main differences in running Selenium for testing and for automating those tasks, is that when you’re testing – if a step fails – the test fails and that’s good enough. All you need is to abort the script and report it back to Testuff via our Automation API. However, for checking your online bank balance, you might want your selenium script to be a little, erm, more intelligent! It should keep trying a few times if a step fails. It should perhaps restart the whole process and try again. It could in fact ignore a few small issues and carry on. Maybe the web page didn’t load completely, but the link to the next page is available. Maybe if a link or text is not available, clicking on another link and then re-loading the page helps.
We’re using python primarily. It’s a simple and powerful language, very easy to read and write, and Selenium easily exports scripts to it. I’ll just list a couple of simple helper functions that I ended up using. They are fairly self-explanatory, but feel free to comment if you have a question.
def wait_for_text(self, text, wait=60): """ Waits for text to appear on screen for a given number of seconds. It does not raise any exception if the text is not present, but rather returns False """ sel = self.selenium for i in range(wait): try: self.failUnless(sel.is_text_present(text)) break except: pass time.sleep(1) return False def wait_until_text_disappears(self, text, wait=60): """ Waits for text to disappear off screen for a given number of seconds. It does not raise any exception if the text is still present, but rather returns False. This is useful for some websites which put pages like "processing your request" """ sel = self.selenium for i in range(wait): try: self.failIf(sel.is_text_present(text)) break except: pass time.sleep(1) return False def wait_for_page(self, wait): """ Replaces the wait_for_page_to_load built-in function, but catches any exception, so the script can carry on despite the page not being fully loaded. """ sel = self.selenium try: sel.wait_for_page_to_load("%d" % wait * 1000) except Exception, e: print "Exception caught: %s" %e
A ‘typical’ automation script will look something like (simplified slightly):
def get_mobile_balance(self): """ retrieves the mobile phone and remaining Mb balance and emails it It retries several times, in case there's a temporary issue with the website. """ sel = self.selenium retry_count = 0 MAX_TRIES = 5 while retry_count <= MAX_TRIES: try: balance = self._get_balance(sel) self._email("email@example.com", "Mobile Phone Balance", "Here's your balance for today: %s" % balance) except: retry_count = retry_count + 1 if retry_count >= MAX_TRIES: raise time.sleep(15) def _get_balance(self, sel): sel.open(sel.browserURL) sel.click("//div[@id='check_balance']/div/div/a/h2") sel.click("link=mobile phone") self.wait_for_page(30) sel.type("txtMobileNo", "12345678") sel.type("txtPassword", "my_password") sel.click("continue") self.wait_for_page(30) self.wait_for_text("Account is ready.") sel.click("//input[@type='image']") self.wait_for_text("Your Package", 60) sel.click("link=view your current usage") self.wait_for_page(30) self.wait_until_text_disappears("processing... please wait", 60) self.wait_for_text("view package balance", 60) sel.click("link=view package balance") self.wait_for_page(30) self.wait_until_text_disappears("processing... please wait", 60) self.wait_for_text("minutes available", 60) remaining_minutes = sel.get_text("//div/span") remaining_mb = sel.get_text("//div/div/span") sel.click("link=log out") return "%sn%s" % (remaining_minutes, remaining_mb) def _email(self, email_address, subject, bodyText): ...
Feel free to share any other cool ideas for using Selenium, or any other automation tool.