《手把手教你》系列進階篇之4-python+ selenium自動化測試 – python幾種超神操作你都知道嗎?(詳細教程)
- 2019 年 12 月 20 日
- 筆記
1. 簡介
今天分享和講解的超神操作,對於菜鳥來說是超神的操作,對於大佬來說也就是幾個簡單方法的封裝和調用。這裡講解和分享這部分主要是為了培養小夥伴們和童鞋們的面向對象的開發思維,對比這樣做的好處讓你自己身臨其境的感受一番。
2. 自定義封裝一個簡單的Log類
本文介紹如何寫一個Python日誌類,用來輸出不同級別的日誌信息到本地文件夾下的日誌文件里。為什麼需要日誌輸出呢,我們需要記錄我們測試腳本到底做了什麼事情,最好的辦法是寫事件監聽。這個事件監聽,對我們現在來說,還是有點複雜去理解,所以我這裡,選擇封裝一個簡單的日誌類,同樣達到這個效果。
我們大概需要如下日誌輸出效果:

2.1 問題分析:
我們需要封裝一個簡單的日誌類,主要有以下內容:
1. 生成的日誌文件格式是 年月日時分秒.log
2. 生成的xxx.log文件存儲在項目根目錄下Logs文件夾下
3. 這個日誌類,支持INFO,ERROR兩種日誌級別
4. 日誌里,每行日誌輸出,如上圖,時間日期+執行類名稱+日誌級別+日誌描述
2.2 解決問題思路:
1. 在根目錄下新建一個Logs的文件夾,如何獲取這個Log的相對路徑,前面介紹過。
2. 日誌的保存命名,需要系統時間,前面也介紹過時間格式化輸出
3. Python中有一個logging模塊來支持我們自定義封裝一個新日誌類。
4. 在腳本里,初始化一個日誌類的實例對象,然後去控制輸出INFO還是ERROR日誌信息。
自定義日誌類封裝如下:logger.py,新建在test包下
2.3 代碼實現:

2.4 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 import logging import os.path import time class Logger(object): def __init__(self, logger): """ 指定保存日誌的文件路徑,日誌級別,以及調用文件 將日誌存入到指定的文件中 :param logger: """ # 創建一個logger self.logger = logging.getLogger(logger) self.logger.setLevel(logging.DEBUG) # 創建一個handler,用於寫入日誌文件 rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time())) print(os.getcwd()) log_path = (os.path.dirname(os.getcwd() + '\Logs\')) print(log_path) log_name = log_path + rq + '.log' fh = logging.FileHandler(log_name) fh.setLevel(logging.INFO) # 再創建一個handler,用於輸出到控制台 ch = logging.StreamHandler() ch.setLevel(logging.INFO) # 定義handler的輸出格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) ch.setFormatter(formatter) # 給logger添加handler self.logger.addHandler(fh) self.logger.addHandler(ch) def getlog(self): return self.logger
2.5 新建日誌測試類
新寫一個測試日誌類,相關代碼如下:
2.5.1 代碼實現:

2.5.2 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 import time from selenium import webdriver from test1.logger import Logger mylogger = Logger(logger='test_log').getlog() class TestMyLog(object): def print_log(self): driver = webdriver.Chrome() mylogger.info("打開瀏覽器") driver.maximize_window() mylogger.info("最大化瀏覽器窗口。") driver.implicitly_wait(8) driver.get("https://www.baidu.com") mylogger.info("打開百度首頁。") time.sleep(1) mylogger.info("暫停一秒。") driver.quit() mylogger.info("關閉並退出瀏覽器。") testlog = TestMyLog() testlog.print_log()
2.5.3 運行結果:
運行代碼後,控制台打印如下圖的結果

2.5.4 文件保存結果:
運行代碼後,在Logs文件夾下可以看到日誌文件,如下圖的結果

在PyCharm里運行下這個測試類,會在根目錄下的Logs文件下,新建一個日誌文件,打開效果如文章開頭的日誌輸出圖。好了,關於自定義封裝log類,自己好好去讀下代碼,理解下每行代碼的意思,日誌類的封裝和調用就介紹到這裡。
3. 把截圖類方法封裝到前面的BasePage.py
本文介紹把截圖類方法封裝到BasePage.py文件里,這個文件是在前面Selenium方法二次封裝文章里創建的,具體代碼請到前面這篇里找。我們截圖類寫死了把截圖圖片保存到根目錄下的Screenshots文件夾里,圖片名稱是當前系統時間,圖片後綴名是png。
新的BasePage.py內容如下:
3.1 代碼實現:

3.2 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 import os import time from test1.logger import Logger mylog = Logger(logger='BasePage').getlog() class BasePage(object): """ 主要是把常用的幾個Selenium方法封裝到BasePage這個類,我們這裡演示以下幾個方法 back() forward() get() quit() """ def __init__(self, driver): """ 寫一個構造函數,有一個參數driver :param driver: """ self.driver = driver def back(self): """ 瀏覽器後退按鈕 :param none: """ self.driver.back() def forward(self): """ 瀏覽器前進按鈕 :param none: """ self.driver.forward() def open_url(self, url): """ 打開url站點 :param url: """ self.driver.get(url) def quit_browser(self): """ 關閉並停止瀏覽器服務 :param none: """ self.driver.quit() def take_screenshot(self): """ 截圖並保存在根目錄下的Screenshots文件夾下 :param none: """ file_path = os.path.dirname(os.getcwd()) + '/Screenshots/' rq = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) screen_name = file_path + rq + '.png' try : self.driver.get_screenshot_as_file(screen_name) mylog.info("開始截圖並保存") except Exception as e: mylog.error("出現異常",format(e))
3.3 新建截圖類
主要看最後一個截圖類方法的封裝。
測試類相關代碼如下:
3.3.1 代碼實現:

3.3.2 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 import time from selenium import webdriver from blog.basepage import BasePage class TestScreenshot(object): driver = webdriver.Chrome() driver.maximize_window() driver.implicitly_wait(10) basepage = BasePage(driver) def test_take_screen(self): self.basepage.open_url("https://www.baidu.com") time.sleep(1) self.basepage.take_screenshot() self.basepage.quit_browser() test = TestScreenshot() test.test_take_screen()
3.3.3 運行結果:
運行代碼後,控制台打印如下圖的結果

3.3.4 截圖保存結果:
運行代碼後,在Screenshots文件夾下可以看到截圖文件,如下圖的結果

運行後,可以在根目錄下Screenshots文件夾里找到百度首頁截圖。

本文就介紹了截圖類方法添加到BasePage里,介紹了如何保存到根目錄下的Screenshots文件夾。
4. Python中的繼承的使用
本文開始介紹一個面向對象設計領域裏,很常見的一種思想,繼承。繼承有很多好處,常聽到的一句話就是,子類能夠直接使用父類的方法,這樣就可以減少子類代碼量。其實,在自動化測試框架設計過程中,是很有必要把繼承加入到你的測試腳本中去。接下來我們,簡單寫一個Python文件,來演示下繼承的基本使用。
4.1 新建classA.py
1. 在test1包名下新建一個classA.py,這個就是我們的父類,裏面有一個打開chrome瀏覽器和打開百度首頁的方法。
4.1.2 代碼實現:

4.1.3 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 from selenium import webdriver import time class ClassA(object): def open_baidu(self): driver = webdriver.Chrome() driver.maximize_window() driver.get("https://www.baidu.com") time.sleep(1) driver.quit()
4.2 新建classB.py
1. 在test2包下新建一個classB.py文件,這個繼承classA.py里的ClassA類。
4.2.1 代碼實現:

4.2.2 參考代碼:
# coding=utf-8? # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.注釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-12-16 @author: 北京-宏哥 QQ交流群:705269076 Project: 《手把手教你》系列進階篇之4-python+ selenium自動化測試 - python基礎掃盲 ''' # 3.導入模塊 from test1.classA import ClassA class ClassB(ClassA): def test_inherit(self): self.open_baidu() test = ClassB() test.test_inherit()
4.2.3 運行結果:
運行代碼後,控制台打印如下圖的結果

通過上面可以看出,只需要一句代碼就可以實現ClassA中的方法,這個就是繼承的好處,減少了很多代碼的書寫,提高代碼的復用。在定義ClassB的時候就要指明ClassB的父類是ClassA. 繼承相關的話題就介紹到這裡,將在後面自動化框架設計會再次提到。
5. 小結
5.1 中文亂碼
遇到的問題:細心地小夥伴或者同學們會發現在日誌文件中的內容或出現中文亂碼,如下圖示:

解決辦法:在FileHandler
此處要設置 encoding 格式,
fh = logging.FileHandler(log_name,encoding='utf-8')

修改後,運行代碼日誌文件內容如下圖所示:

5.2 路徑問題
因為宏哥在代碼實踐的過程中這部分遇到小問題,就是日誌文件和截圖放不在指定的文件夾下,所以這裡拿出來單獨說一下。
# 創建一個handler,用於寫入日誌文件 rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time())) #當前目錄 print(os.getcwd()) #根目錄 print(os.path.dirname(os.getcwd())) #log_path = (os.path.dirname(os.getcwd())+ '\Logs\') log_path = os.getcwd() + '\Logs\' print(log_path)
代碼說明:
os.getcwd() :獲取的當前最外層調用的腳本路徑,即getPath所在的目錄也可描述為起始的執行目錄,A調用B,起始的是A,那麼獲取的就是A所在的目錄路徑。
os.path.dirname():去掉腳本的文件名,返回目錄。
好了,今天的分享就到這裡吧!!!謝謝各位的耐心閱讀。