這個仍是我在剛開始學習selenium的時候作的,本身以爲有點意思,在接下來我會基於目前我對於selenium的一些深刻研究,寫下我對selenium的理解以及UIAutomation的一些理解,以此開篇吧^_^web
前段時間研究Selenium,寫了一些測試網頁的代碼,寫着寫着,就感受這些自動化cases的類似度過高,多數是大同小異,基本上能夠概括爲這樣三步1)找到元素 2)進行操做, 好比點擊或者滑動 3) 驗證指望, 好比跳轉到了一個新頁面,或者新元素出如今屏幕中.app
好比下面:工具
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait def web_automation(): browser=webdriver.Chrome() browser.get('http://www.baidu.com/') Input_element=browser.find_element_by_id('kw') Input_element.send_keys('Selenium') browser.find_element_by_id('su').click() result=browser.find_element_by_xpath('//*[@id="container"]/div[2]').is_displayed() assert result!=True,"Failed"
寫的多了,這時候就想,能不能有什麼模板,讓咱們快速的建立一條case,甚或者能讓一個不會Selenium的Tester也能寫自動化case呢。學習
說作就作,最後就搞出來了下面一個雛形, 咱們能夠定義這樣的一個XML:測試
<TestCase name="ClickBackButton" scriptVersion="1.0.0"> <Executable>Chrome</Executable> <Address>http://www.baidu.com</Address> <Action Operate="InputSearchInfo" Type="Input" ID="kw" Content="Glow"/> <Action Operate="Scroll" Type="Scroll" /> <Action Operate="ClickNextPageHLink" Type="Click" XPath='//*[@id="page"]/a[10]'> <Expected XPath='//*[@id="page"]/strong/span[2]' Text="2" /> </Action> <Action Operate="Goback" Type="Back"> <Expected XPath='//*[@id="page"]/strong/span[2]' Text="1" /> </Action> <Action Operate="Scroll" Type="Scroll" /> <Action Operate="ClickPage6" Type="Click" XPath='//*[@id="page"]/a[5]'> <Expected XPath='//*[@id="page"]/strong/span[2]' Text="6" /> </Action> <Action Operate="Goback" Type="Back"> <Expected XPath='//*[@id="page"]/strong/span[2]' Text="1" /> </Action> </TestCase>
而後咱們就能夠這樣來解析:ui
第一步解析XML生成TestCase的list,在例子中就一個Testcase:spa
import xml.etree.ElementTree as ET import logging import os import sys import traceback from TestCase import TestCase class ParseCase: def __init__(self,xml_path): if os.path.exists(os.getcwd()+"\\"+xml_path) or os.path.exists(xml_path): self.caseList=[] try: xml=ET.parse(xml_path) root=xml.getroot() self.caseList=root.find('TestList').findall('TestCase') except IOError as e: print traceback.format_exc() logging.debug(traceback.format_exc()) if self.caseList: logging.info('No Testcase detected') else: logging.info('No Testcase detected') else: print "XML file is not exists" logging.debug("XML file is not exists") def getAllTestCaseList(self): TestCases=[] for case in self.caseList: _testcase=TestCase(case) TestCases.append(_testcase) return TestCases
第二步, 根據每一個testcase創建TestCase類的實例:debug
class TestCase: def __init__(self, _testcase): self.name=_testcase.attrib['name'] _list=[] self.actions=[] try: _list=_testcase.getchildren() except Exception,msg: print msg self._executor=_testcase.find('Executable').text self.address=_testcase.find('Address').text for act in _testcase.findall('Action'): if act.tag=='Action': _action=Action(act) self.actions.append(_action) def setUp(self): if 'Chrome'==self._executor: self.executor=webdriver.Chrome() elif 'Firefox'==self._executor: self.executor=webdriver.Firefox() else: self.executor=webdriver.Ie() self.executor.get(self.address) def tearDown(self): self.executor.quit() def execute(self): logging.debug("Start to execute the testcase:%s" % self.name) print "TestCaseName:%s" % self.name try: self.setUp() for action in self.actions: action.execute(self.executor); self.tearDown() Assert.AssertPass("TestCase:%s " % self.name) except Exception as error: print error self.tearDown() Assert.AssertFail("TestCase:%s " % self.name)
第三步,根據xml裏定義的type來觸發動做,我就簡單的列了下:code
def execute(self,executor): _type=self._actions['Type'] self.getBy(self._actions) try: if self.by!=None: ele=self.findElement(executor) Assert.AssertIsNotNull(ele," ".join("Find element by %s:%s" % (str(self.by),self.by_value))) if _type=='Input': ele.send_keys(self._actions['Content']) time.sleep(3) elif _type=='Click': ele.click() elif _type=='Scroll': webOperate.page_scroll(executor) elif _type=='Back': webOperate.goBack(executor) else: print " ", Assert.AssertFail(self._name) print "No such action:%s" % _type if self._expected is not None: Assert.AssertIsTrue(self.isExpected(executor)," ".join("Find element by %s:%s" % (str(self.by),self.by_value))) print " ", Assert.AssertPass(self._name) except AssertionError: print " ", Assert.AssertFail(self._name) raise AssertionError(self._name +" execute failed")
看一個運行的截圖orm
代碼比較簡單,原理也很清晰,就是解析XML文件,而後調用相應的selenium代碼,可是若是咱們再深刻的想一想,在解析這些XML的時候,是否是能夠以更友好的方式來展現生成的代碼呢,甚或者以UI的方式,一條條展現。而後再提供可編輯功能?甚或者再提供錄製的方式來自動生成這些XML文件,再解析成代碼,這不就是一個強大的自動化測試工具??