1. 程式人生 > >python 和 selenium實現web UI功能自動化測試框架(米兔888)

python 和 selenium實現web UI功能自動化測試框架(米兔888)

之前分享了python和requests搭配實現的介面自動化測試框架,今天,我再來整理分析下基於python和selenium的web UI自動化測試,希望能對大家有所幫助,也是自己整理知識學習的方法,跟大家一起努力,奮鬥在自動化測試的道路上。

其實UI自動化和介面自動化框架的設計思路大同小異,主要目的還是分離業務程式碼和測試資料,達到程式碼的複用,提高測試用例的可維護性以及最最重要的減少人工勞動力。那麼就開始直接看正文吧。

設計目的:

分離業務程式碼和測試資料,提高程式碼可維護性,實現自動化,減少重複勞動,最終達到“偷懶”的目的,哈哈哈哈哈~~ 哎呦,不好意思,一不小心暴露了真相。小編是真的在一本正經的寫程式碼啦。

框架目錄結構:

        case:存放具體的測試程式碼

        comm:存放共通的方法

        file:存放測試用例等測試過程中用到的測試資料

        result:每次測試的log和測試報告的存放位置

        caseList:規定執行哪些測試

        config:配置靜態資料

                                                                readConfig:讀取config檔案內容

                                                                runAll:測試執行入口檔案

一起來看整個框架的搭建。

首先,要保證你的python已經安裝了selenium包,如果你是用pip來管理自己的python環境的,那麼你可以通過下面的命令來匯入selenium模組:

pip install selenium

然後,你需要到網上去下載對應瀏覽器的驅動,這裡小編使用的是chrome瀏覽器,(chrome下載地址:http://chromedriver.storage.googleapis.com/index.html)。下載完成之後呢,將下載的瀏覽器驅動放到本地的python安裝目錄下,這樣就可以直接在框架中使用了。至此,必備的條件都有了,我們就可以開工啦。

這裡呢,我們就只挑部分內容進行講解,有許多跟介面測試框架相同或相似的方法和檔案,就不一一進行二次說明了,第一次看的盆友們,有不明白的地方可以看這篇文章,進行補充學習

https://my.oschina.net/u/3041656/blog/820023

開啟瀏覽器:

from selenium import webdriver

classDriver:

    def__init__(self):
        
        self.browser = webdriver.Chrome()

    defopen_browser(self):
        """
        Do something for browser
        :return: browser
        """
        # 視窗最大化
        self.browser.maximize_window()

        # 開啟地址連結
        url = 'http://www.baidu.com'
        self.browser.get(url)
        return self.browser

    defclose_browser(self):
        """
        quit browser
        :return:
        """
        self.browser.quit()

從上面的程式碼可以看出,我們進行了開啟/關閉瀏覽器的方法定義,只有簡單的幾行程式碼,當然了,這裡為了方便大家觀看,我把url地址直接寫了出來,在實際操作時,我們可以將其抽離出來,根據自己的需要,傳入不同的url地址。這就留著讓大家去自己實現吧。

一個簡單的搜尋栗子:

from time import sleep
from selenium import webdriver
import unittest


classLogin(unittest.TestCase):

    defsetUp(self):
        self.driver = webdriver.Chrome()

        # 視窗最大化
        self.driver.maximize_window()
        self.msg = '海賊王'
        self.url = 'http://www.baidu.com'

    deftestSearch(self):
        """
        test body
        :return:
        """
        # open browser
        self.driver.get(self.url)
        sleep(3)
        # click search input
        self.driver.find_element_by_id('kw').click()
        sleep(1)

        # input value
        self.driver.find_element_by_id('kw').send_keys(self.msg)
        sleep(1)
        self.driver.find_element_by_id('su').click()
        sleep(1)

    deftearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main()

在上面的程式碼裡,我們在百度裡搜尋了小編最愛的動漫,嘻嘻,是不是很開心啊,就這樣邊學邊玩耍,感覺測試也是美美的。

selenium可以通過很多種方式來定位元素。這個讀者可以自行學習。

大家看到了,這就是UI測試的雛形,有了這個雛形,我們就可以對它進行擴充套件,擴充套件,最後搭出框架來。

新增log日誌:

在上面的基礎上,我們可以新增執行時輸出的log日誌。所以開始寫log檔案,並將它放在comm資料夾下,作為共同方法來用。這部分內容在介面測試框架那裡已經介紹過了,所以請還不清楚的朋友們移步此處:https://my.oschina.net/u/3041656/blog/820023

抽離出瀏覽器的相關操作:

我們可以將對瀏覽器的操作剝離出來,單獨放到一個檔案中,這樣既清晰,又避免了重複的程式碼操作。而且維護起來也比較方便。

from selenium import webdriver
from comm.Log import MyLog as Log
import readConfig
import threading

localReadConfig = readConfig.ReadConfig()


classDriver:

    def__init__(self):
        self.log = Log.get_log()
        self.logger = self.log.get_logger()

        self.browser = webdriver.Chrome()

    defopen_browser(self, name1, name2):
        """
        Do something for browser
        :return: browser
        """
        self.logger.info("Open browser")

        # 視窗最大化
        self.browser.maximize_window()

        # 開啟地址連結
        url = localReadConfig.get_webServer(name1, name2)
        self.browser.get(url)
        return self.browser

    defclose_browser(self):
        """
        quit browser
        :return:
        """
        self.browser.quit()
        self.logger.info("Quit browser")

    defget_driver(self):
        """
        get web driver
        :return:
        """
        return self.browser


classMyDriver:

    driver = None
    mutex = threading.Lock()

    def__init__(self):
        pass

    @staticmethod
    defget_browser():

        if MyDriver.driver is None:
            MyDriver.mutex.acquire()
            MyDriver.driver = Driver()
            MyDriver.mutex.release()

        return MyDriver.driver

if __name__ == "__main__":
    driver = MyDriver.browser()
    browser = driver.open_browser()

以上便是小編剝離出來的部分,並且將它放到了單獨的執行緒中。

有木有覺得眼熟呢?其實就跟log的原理是一樣的啦。這就是“舉一反三”哦,套路就是那個套路,就看你怎麼用了。

關於Element的那些事兒:

做過UI功能測試的朋友們應該都知道,元素是我們測試最基本也是最重要的東西,以為它是我們直接的操作物件,所以,處理好它們,我們就會省掉很多的麻煩,所以呢,接下來,小編將會繼續分享自己處理element的一些方法,希望能對大家有所幫助,如果哪位大神有更好的方法,請一定要告訴小編哦!小編在此先謝過了!

classElement:

    def__init__(self, activity_name, element_name):

        self.driver1 = Driver.get_browser()
        self.driver = self.driver1.get_driver()
        self.activity = activity_name
        self.element = element_name
        element_dict = get_el_dict(self.activity, self.element)
        self.pathType = element_dict.get('pathType')
        self.pathValue = element_dict.get('pathValue')

    defis_exist(self):
        """
        Determine element is exist
        :return: TRUE OR FALSE
        """
        try:
            if self.pathType == 'ID':
                self.driver.find_element_by_id(self.pathValue)
                return True
            if self.pathType == 'XPATH':
                self.driver.find_elements_by_xpath(self.pathValue)
                return True
            if self.pathType == 'CLASSNAME':
                self.driver.find_element_by_class_name(self.pathValue)
                return True
            if self.pathType == 'NAME':
                self.driver.find_element_by_name(self.pathValue)
                return True
        except NoSuchElementException:
            return False

    defwait_element(self, wait_time):
        """
        wait element appear in time
        :param wait_time: wait time
        :return: true or false
        """
        time.sleep(wait_time)
        if self.is_exist():
            return True
        else:
            return False

    defget_element(self):
        """
        get element
        :return: element
        """
        try:
            if self.pathType == 'ID':
                element = self.driver.find_element_by_id(self.pathValue)
                return element
            if self.pathType == 'XPATH':
                element = self.driver.find_elements_by_xpath(self.pathValue)
                return element
            if self.pathType == 'CLASSNAME':
                element = self.driver.find_element_by_class_name(self.pathValue)
                return element
            if self.pathType == 'NAME':
                element = self.driver.find_element_by_name(self.pathValue)
                return element
        except NoSuchElementException:
            return None

    defget_element_by_index(self, index):
        """
        get element by index
        :param index: index
        :return: element
        """
        try:
            if self.pathType == 'ID':
                element = self.driver.find_element_by_id(self.pathValue)
                return element[index]
            if self.pathType == 'XPATH':
                element = self.driver.find_elements_by_xpath(self.pathValue)
                return element[index]
            if self.pathType == 'CLASSNAME':
                element = self.driver.find_element_by_class_name(self.pathValue)
                return element[index]
            if self.pathType == 'NAME':
                element = self.driver.find_element_by_name(self.pathValue)
                return element[index]
        except NoSuchElementException:
            return None

    defget_element_list(self):
        """
        get element list
        :return: element list
        """
        try:
            if self.pathType == 'ID':
                element_list = self.driver.find_element_by_id(self.pathValue)
                return element_list
            if self.pathType == 'XPATH':
                element_list = self.driver.find_elements_by_xpath(self.pathValue)
                return element_list
            if self.pathType == 'CLASSNAME':
                element_list = self.driver.find_element_by_class_name(self.pathValue)
                return element_list
            if self.pathType == 'NAME':
                element_list = self.driver.find_element_by_name(self.pathValue)
                return element_list
        except NoSuchElementException:
            return None

    defclick(self):
        """
        click element
        :return:
        """
        element = self.get_element()
        time.sleep(1)
        element.click()

    defsend_key(self, key):
        """
        input key
        :param key: input value
        :return:
        """
        element = self.get_element()
        time.sleep(1)
        element.clear()
        element.send_keys(key)

    definput_keys(self, index, key):
        """
        By index send key
        :param index: index
        :param key: key
        :return:
        """
        element = self.get_element_by_index(index)
        time.sleep(1)
        element.clear()
        element.send_keys(key)

    defget_text_value(self):
        """
        get attribute
        :return:
        """
        element = self.get_element()
        value = element.get_attribute('text')
        return str(value)

這是小編寫的,目前能用到的關於element的方法了,累覺不愛啊~

但是,生活還要繼續,工作還未完成。所以,請讓我講完剩下的程式碼吧!!!

那些讓人費神的測試資料檔案:

每一個好的測試,都離不開一份好的測試用例資料,那麼,這麼多的資料,我們要怎樣進行管理才能既不亂又方便以後對資料進行更改維護呢?下面,小編就要告訴朋友們一個重磅訊息,敲黑板!!!

其實,小編也不知道有什麼好辦法,小編就是使用excel檔案來對測試用例進行統一管理的。請看下面:

形式就是這麼個形式,內容就隨便你們怎麼修改了。畢竟我也只能幫你們到這裡了。至於對excel檔案內容的讀取,在介面測試那篇博文中也有詳細介紹哦。不明白的同學請移步:https://my.oschina.net/u/3041656/blog/820023

其實,出來測試用例,還有一個數量龐大的資料群體,快猜猜它們是誰???

噹噹噹,答案就是:元素定位的資料,包括:id,name,classname,xpath等等,這些資料可是我們在測試過程中找到頁面元素的不二法門哦。。。所以各位朋友一定要注意啦,一定要處理好它們。

請看下面:

愚蠢的小編就用xml檔案來管理啦。

是不是又有人想問怎麼讀取xml檔案了?嘿嘿。。。我不會告訴你的,因為我在前面的博文裡已經講過啦!講過啦!過啦!啦!!

至此呢,今天的內容也結束了,希望對大家有所啟發和幫助,雖然講的有些凌亂,不過只要弄懂了這些劃分和實現方法,我相信,你也一定可以寫出自己滿意的UI自動化測試框架。所以,我們一起加油吧。

本文為原創文章,轉載請註明原文地址,謝謝大家的支援。希望大家一起努力成長。

如果覺得本文的文章寫得很好,打個賞,多少都行~~~


如果覺得本文的文章寫得很好,打個賞,多少都行~~~

相關推薦

no