1. 程式人生 > 實用技巧 >36 web自動化實戰二 pytest用例篩選 斷言 生成測試報告 資料驅動

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 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.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 就是不相容。