36 web自動化實戰二 pytest用例篩選 斷言 生成測試報告 資料驅動
79節
目錄
1.pytest 篩選用例
2.pytest的斷言 assert
3.測試報告
4.pytest用例執行順序
5.資料驅動
1.pytest 篩選用例:標記功能
1).標籤打在整個測試類上面
舉例,在上面的登入測試用例的測試類上面加標籤:@pytest.mark.login
①在pytest.ini檔案中加上標籤名:login
②在TestLogin類上面加@pytest.mark.login
③terminal中執行 pytest -m "login"
程式碼實現:
"""登入功能的測試用例""" import unittest import pytest from middware.handler importHandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登入功能的測試類""" @pytest.mark.error def test_login_error(self): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return:""" from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待 等待的時間就可以放在config中,直接引數呼叫 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time)#2.訪問登入頁面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys("") #定位輸入手機號為空 driver.find_element_by_name("password").send_keys("")#定位輸入的密碼為空 driver.find_element_by_class_name("btn-special").click() #4.通過獲取頁面內容得到實際結果,進行斷言 #實際結果是在頁面上的提示,再次進行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #斷言 self.assertTrue(actual_result == "請輸入手機號") # @pytest.mark.success def test_login_success(self): """登入成功測試用例 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待時間 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] driver.implicitly_wait(wait_time) #2.訪問登入頁面 url="http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys("15*********") driver.find_element_by_name("password").send_keys("15") driver.find_element_by_class_name("btn-special").click() #4.獲取實際結果,進行斷言 actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text print(type(actual_result)) self.assertTrue("我的帳戶[小蜜蜂177872141]" in actual_result)
執行結果:
2).標記功能組合------不同的testcase的py檔案中,可以同時執行多個
語法1.:
pytest -m "register_error orsuccess" -------只需要滿足一個條件就可以執行(可以組合2個或者2個以上)
pytest -m "register_error and success" -------2個條件同事滿足才可以執行(可以組合2個或者2個以上)
pytest -m "register_error and not success" -------2個條件同事滿足才可以執行(可以組合2個或者2個以上),取非
舉例:執行test_register.py中的register_error,或者test_login中的success
首先別忘記在ini檔案中註冊tagname
程式碼實現:
test_register.py:
import unittest import pytest class TestRegister(unittest.TestCase): """註冊功能的測試類""" @pytest.mark.register_error def test_register_error(self): pass
test_login.py:
"""登入功能的測試用例""" import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登入功能的測試類""" @pytest.mark.error def test_login_error(self): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待 等待的時間就可以放在config中,直接引數呼叫 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.訪問登入頁面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys("") #定位輸入手機號為空 driver.find_element_by_name("password").send_keys("")#定位輸入的密碼為空 driver.find_element_by_class_name("btn-special").click() #4.通過獲取頁面內容得到實際結果,進行斷言 #實際結果是在頁面上的提示,再次進行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #斷言 self.assertTrue(actual_result == "請輸入手機號")
執行pytest -m "register_error or success",結果:
3)標記功能組合---------一個函式或者類上面,可以加多個標籤
例1: 標籤組合and
程式碼如下:
"""登入功能的測試用例""" import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登入功能的測試類"""
@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver 。 。 。 。
執行:pytest -m "login and smoke" ,類標籤有2個方法,但是and smoke,表示只篩選類裡面的標記為smoke的方法。、
結果:
例2: 標籤組合 not
執行TestLogin這個類下面的success的方法(success方法沒有打標籤)
執行:pytest -m "login and not smoke"
或者pytest -m "login and not error"
import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登入功能的測試類"""
@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待 等待的時間就可以放在config中,直接引數呼叫 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.訪問登入頁面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys("") #定位輸入手機號為空 driver.find_element_by_name("password").send_keys("")#定位輸入的密碼為空 driver.find_element_by_class_name("btn-special").click() #4.通過獲取頁面內容得到實際結果,進行斷言 #實際結果是在頁面上的提示,再次進行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #斷言 self.assertTrue(actual_result == "請輸入手機號") def test_login_success(self): """登入成功測試用例 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待時間 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] driver.implicitly_wait(wait_time) #2.訪問登入頁面 url="http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys("15********") driver.find_element_by_name("password").send_keys("15") driver.find_element_by_class_name("btn-special").click() #4.獲取實際結果,進行斷言 actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text print(type(actual_result)) self.assertTrue("我的帳戶[小蜜蜂177872141]" in actual_result)
注意:用例標記的時候,標籤如果有邏輯運算,一定要加雙引號。
2.pytest的斷言 assert
背景:上篇部落格中有提到,pytest是可以脫離類存在的,所以單個函式的斷言,是用不了self.assertTrue
1).pytest 的斷言直接用assert即可
assert 3>2、assert 4=4 這樣表述即可。
3.測試報告
1).安裝HTML的測試報告 pip install pytest-html
2).執行結果生成報告:pytest -m "login and not error" --html=report.html
即可在專案下生成測試報告。
3).測試報告生成時間戳:指令碼執行pytest
①在run.py檔案中,以pytest.main()形式執行用例。
首先看下main()方法的原始碼:引數表示:列表形式的命令列引數;外掛暫時用不到,先不看
run.py如下:
"執行測試用例" import pytest if __name__ == '__main__': pytest.main(["--html=report1.html"])
下面將測試報告加上時間戳:
①import datatime
②ts = datatime.datetime.now()strftime("%Y-%m-%d-%H-%M-%S")
run.py實現:
"執行測試用例" import pytest import datetime ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") if __name__ == '__main__': pytest.main(["--html={}report.html".format(ts)])
4.pytest用例執行順序
類裡面的用例方法:從上到下,執行(簡單來說,想讓哪個用例先執行,就把用例寫在前面)
5.資料驅動 79節45min
首先,回顧下,如果用unittest框架去測試,程式碼如下:
"""登入功能的測試用例""" import ddt import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time data = HandlerMiddle.excel.read_data("login") @ddt.ddt class TestLogin(unittest.TestCase): """登入功能的測試類""" @ddt.data(*data) def test_login_error(self,test_info): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待 等待的時間就可以放在config中,直接引數呼叫 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.訪問登入頁面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"]) driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"]) driver.find_element_by_class_name("btn-special").click() #4.通過獲取頁面內容得到實際結果,進行斷言 #實際結果是在頁面上的提示,再次進行定位 actual_result = driver.find_element_by_class_name("form-error-info").text expected_result = test_info["expected_result"] #斷言 self.assertTrue(actual_result == expected_result)
通過pytest用例篩選執行error用例,讀取web_excel.xlsx中的2條用例(一條通過,一條不通過),run,py程式碼如下:
"執行測試用例" import pytest import datetime ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") if __name__ == '__main__': pytest.main(["--html={}report.html".format(ts), "-m error"])
用unittest框架(使用篩選用例)的資料驅動,執行通過。
下面用pytest的資料驅動完成測試:
pytest資料驅動的語法:
①在用例的方法上新增:@pytest.mark.parametrize("test_info",data) data表示列表表示的資料
② 用例方法中新增引數test_info
注:pytest中,類上面不需要加任何東西(因為它可能沒有類)
pytest中,parametrize中的第一個引數“test_info” 跟函式中的引數名稱必須是一致的------->(def test_login_error(self,test_info):)
完成上面的操作後,還有需要跟unittest區分的是:不能繼承unittest.TestCase,斷言就不能用self.assertTrue了
程式碼實現如下:
"""登入功能的測試用例""" import pytest from middware.handler import HandlerMiddle from config.config import Wait_time data = HandlerMiddle.excel.read_data("login") @pytest.mark.login class TestLogin(): """登入功能的測試類""" @pytest.mark.smoke @pytest.mark.error @pytest.mark.parametrize("test_info",data) def test_login_error(self,test_info): """登入失敗測試步驟 1.開啟瀏覽器 2.訪問登入頁面 3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 4.通過獲取頁面內容得到實際結果,進行斷言 :return: """ from selenium import webdriver #1.開啟瀏覽器 driver = webdriver.Chrome() #設定隱性等待 等待的時間就可以放在config中,直接引數呼叫 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.訪問登入頁面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,輸入使用者名稱和密碼,點選登入 driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"]) #定位輸入手機號為空 driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"])#定位輸入的密碼為空 driver.find_element_by_class_name("btn-special").click() #4.通過獲取頁面內容得到實際結果,進行斷言 #實際結果是在頁面上的提示,再次進行定位 actual_result = driver.find_element_by_class_name("form-error-info").text expected_result = test_info["expected_result"]
#斷言 assert actual_result == expected_result
執行上面的run.py,測試通過。
資料驅動注意事項:
①在使用@pytest.mark.parametrize("test_info",data)做資料驅動時,pytest和unittest不相容,即,如果想使用pytest的資料驅動,就不能繼承unittest.TestCase,並修改斷言
②如果用unittest寫用例,就需要用 unittest 的資料驅動。(類 繼承unittest.TestCase;新增ddt)
總結來說:pytest不跟unittest相容的是:資料驅動parametrize,測試夾具fixture,hook
只要用上面的三個,pytest和unittest 就是不相容。