Python+selenium+unittest的GUI自動化框架實現


框架設計說明圖:

wKioL1dFjXuDuDEzAAhEjEalRlk754.jpg


框架實現前的準備工作:

1.Python版本爲2.7.11的Windows下的安裝。

2.命令行下的selenium最新版本(編者使用版本爲2.53.0,可兼容最新火狐、IE、chrome等瀏覽器版本)pip安裝。

3.版本爲Version: Mars.1 Release (4.5.1)的eclipse安裝(編者Python開發使用工具),jdk1.7。

4.eclipse下Python開發插件PyDev 4.5.1(高版本不一定兼容當前eclipse版本與Java版本,高版本安裝成功後,eclipse中找不到對應PyDev插件)。

5.Python下的MySQL數據庫(編者使用數據爲MySQL)模塊安裝MySQL-python-1.2.4b4.win32-py2.7(注意模塊版本與系統位數,要與安裝Python相同)。

6.Python反編譯模塊uncompyle-master安裝(或許會用到)。

7.Python可執行打包模塊py2exe-0.6.9.win32-py2.7安裝(或許會用到)。


框架實現的可行性:

1.擴展方便,類似於Python的模塊化安裝。

2.易於維護,針對selenium的最新版本升級(兼容瀏覽器的最新版本等)只需命令行下執行:pip install -U selenium即可實現。

3.實現語言簡單易學,針對Python的學習只要是不過於追求高大上(重構、複雜多態等),基本很快時間內即可搞定。

4.各瀏覽器均可兼容使用(編者的其它文章中有介紹IE、chrome等瀏覽器的調用)。


框架實現思路說明:


開篇囉嗦:

    思路說明前,囉嗦兩句(毛病是改不掉了)。小編同事過很多大牛,寫出的代碼非常牛叉(功能、性能、可讀性等),設計的項目框架各種優秀,但是至於很多項目開發人員,很難達到框架設計之初的實現思路,按照初始的框架設計做項目實現。歸根結底是由於項目從事人員未能達到思想上的一致,即框架設計人員未能將框架設計思想很好的傳達給項目從事人員,不能讓項目人員統一實現思想,導致後面項目可能出現的無法進行以及實現過程中的各種困難(項目人員A認爲按照框架能夠實現沙發的製作、項目人員B卻認爲按照框架只能設計出板凳來,思想上的不統一)。更多的事框架的設計未能較好的被理解。不管做什麼,編者始終認爲思路是第一位的。


測試用例代碼實現存放模塊:

import unittest
from time import sleep
from common.driverElement import driverElement

class CrmLoginTest(unittest.TestCase):
    def setUp(self):
        self.driverElement=driverElement()
        self.driver=self.driverElement.webdriverInit('http://crm.360.cn/login')
    def tearDown(self):
        self.driver.quit()
    def testName(self):
        self.driverElement.webdriverLogin(self.driver)
        sleep(4)

    代碼很簡單,定義了系統登錄測試的一個實現類CrmLoginTest,該實現類繼承了unittest模塊的TestCase接口定義的多個方法:setUp、tearDown、testName。

    unittest類似於Java的TestNg,都是用於各自語言單元測試用。只不過實現方式不同罷了。具體看測試實現類繼承的方法,setUp用於測試用例執行前的準備工作,包括數據庫的連接建立、用例需用數據的預製準備等。testName方法定了用例具體實現用到的一些操作,對頁面用戶名、密碼輸入,點擊頁面【登錄】按鈕等一系列的手工測試操作。tearDown方法,用於用例運行完成後的垃圾數據回收、數據庫連接斷開等用例結束操作。

    測試實現類中setUptearDowntestName三方法的執行順序不以出現的先後順序做執行,不管三方法出現的順序爲何,均優先執行setUp,在執行testName、testName1.。。最後執行tearDown

    上面是介紹的測試用例實現思路,測試用例代碼實現存放模塊實現思路是,該模塊下只允許存放測試用例方法(CRMResourcesTest)與測試用例數據文件(Login.json)以及目錄(用於標示測試用例所屬不同層級)。此處區分測試用例方法與測試用例數據文件是自動化實現思想中“數據與腳本分離的重要實現”。數據與腳本分離後便於自動化用例維護(只需維護json文件即可實現用例的維護,無需修改測試腳本)。隨着自動化越做越多,你會發現數據與腳本分離是多麼重要的一件事情。


公共邏輯代碼封裝存放模塊:

    上面代碼中testName方法中只用到了self.driverElement.webdriverLogin方法,即實現了系統登錄。實際的手工測試操作,登錄頁面的完成需要“輸入用戶名”、“輸入密碼”、“點擊【登錄】按鈕”三步實現系統登錄操作。此處只用到了“一步”即實現了系統登錄,怎麼看能,查看公共邏輯代碼封裝存放模塊下的driverElement.py文件,可以看到webdriverLogin方法具體爲:

def webdriverLogin(self,driver):
        elementaction=ElementActionutil()
        elementaction.textinput(driver, elementname='js_uname', method='Class', text=self.f.getGlobalFileattrs('Login.json', 'username'), timeout=2)#用戶名輸入
        elementaction.textinput(driver, elementname='js_upwd', method='Class', text='123456')#密碼輸入
        elementaction.singleclick(driver,elementname='btnsend',method='Id')#點擊【登錄】按鈕
        print 'System login successfully!'

    通過上面代碼可以看到,看到的“一步”,其實際爲三個步驟的一個封裝,此處針對上述三個步驟做封裝,是因爲此三個步驟很多用例中都會用到,封裝之後,各個測試用例直接調用“一步”方法即可實現系統登錄,無需每個用例中均寫三個步驟,代碼美觀易讀,且方便實現。這就是“公共邏輯代碼封裝存放模塊”的存在意義,針對代碼中重複用到的公共步驟封裝存放。當然針對公共步驟的封裝實現用到的測試數據,有公共數據文件存放,如:baseaction下的Login.json文件,存放的就是公共邏輯代碼中用到的數據。


GUI頁面動作代碼存放模塊:

    具體看模塊下elementActionUtil.py文件中singleclick方法:

def singleclick(self,webdriver,elementname='',method='Id',timeout=2):
        'method value:Id,Name,Class,xpath;webdriver value Firefox,Ie'
        element1=waitforElementPresentAction.waitforElementPresentAction(webdriver, elementname, method, timeout)
        element1.click()

    公共邏輯代碼封裝存放模塊中 elementaction.singleclick步驟,其實現就是以上代碼,實際手工測試中鼠標單擊操作,在代碼實現中並不是一個底層方法就可實現的,往往實現起來可能需要N多操作。對誰執行、執行什麼等等。特別是涉及到網絡較差的情況,手工測試知道等待多長時間即可執行單擊操作,但是自動化代碼卻要想方設法完成手工操作的智能化,其實現可想而知。

    此處“GUI頁面動作代碼存放模塊”中,只需包含elementActionUtil.py單文件即可,文件中定義各種頁面操作:鼠標單擊動作、鼠標雙擊動作、文本輸入動作、單選按鈕選擇動作、複選按鈕選擇動作、頁面元素是否可見、元素控件是否存在等等。各種頁面動作的集合,即實現了頁面自動化所需的各種手工實現。


底層代碼模塊:

    底層代碼模塊定義了 公共邏輯代碼封裝存放模塊中 各個動作步驟用到的核心代碼,包括動作執行時間、如何查找元素控件(類似於人眼識別)、針對何種控件執行識別等等,舉例代碼如下:

def waitforElementPresentAction(webdriver,elementname='',method='Id',timeout=2):
    'method value:Id,Name,Class,xpath;webdriver value Firefox,Ie,takes a WebDriver instance and timeout in seconds'
    element1=None
    end_time = time.time() + timeout
    while True:
        try:
            if method=='Id':
                element1=webdriver.find_element_by_id(elementname)
            elif method=='Name':
                element1=webdriver.find_element_by_name(elementname)
            elif method=='Class':
                element1=webdriver.find_element_by_class_name(elementname)
            elif method=='Xpath':
                element1=webdriver.find_element_by_xpath(elementname)
            if element1:
                return element1
        except Exception:
            pass
        if time.time()>end_time:
            assert False,'NoSuchElementException '+elementname+' with the method '+method#此處爲何如此實現,請讀者朋友給個回覆。


文件操作代碼存放模塊:

    該模塊存放了如何實現測試用例數據文件內容讀取操作的各個方法,方法實現的同時,也定義了測試數據文件的儲存格式,數據文件不同後綴形式的讀取等等操作,均存放在“文件操作代碼存放模塊”中。


數據庫代碼存放模塊:

    該模塊定義了針對數據庫的各種操作實現:增、刪、改、查,建表、調用存儲過程等等的數據庫操作。該模塊存在意義就是,手工測試過程中,針對前臺頁面操作完成後,後臺數據庫入表的正確性驗證操作的自動化代碼實現,以及測試用例執行前的測試數據預製實現等等。


日誌文件代碼存放模塊:

    日誌文件代碼存放模塊定義了日誌文件生成如何實現,針對測試用例級實現,運行多個用例、套件級用例運行測試,如何分析用例運行情況,通過用例運行輸出日誌即可實現用例運行正確性的檢查。此處代碼編者暫未實現,後面時間允許會加以完成。


框架不足以及待優化:

    1.單個測試方法如何實現多個測試用例,即如何定義數據文件層級結構等。

    2.日誌文件如何定義實現。

    3.單個用例測試執行、多用例測試執行(套件測試執行)測試報告的輸出等。

    4.代碼傻瓜式實現等。

。。。。。。。。

                                未完、已完、待續。。。。。或許

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章