最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python結(jié)合Pytest打造自動(dòng)化測(cè)試體系

 更新時(shí)間:2026年03月19日 08:34:43   作者:站大爺IP  
這篇文章主要為大家詳細(xì)介紹了Python如何結(jié)合Pytest打造自動(dòng)化測(cè)試體系,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

凌晨?jī)牲c(diǎn),小王盯著屏幕上的報(bào)錯(cuò)信息,額頭冒汗。明天就要上線的新功能,剛才合并代碼后,突然不知道哪里出了問題。更可怕的是,他不確定這個(gè)bug影響了多少功能。這已經(jīng)是本月第三次因?yàn)榛貧w測(cè)試不充分導(dǎo)致的線上故障了。

小王的困境,是無(wú)數(shù)開發(fā)團(tuán)隊(duì)的縮影。手動(dòng)測(cè)試耗時(shí)耗力,覆蓋不全,還容易遺漏。而自動(dòng)化測(cè)試,特別是Python生態(tài)中最優(yōu)雅的pytest框架,正是解決這一困境的良藥。

為什么是pytest

Python的測(cè)試框架不止一個(gè),unittest是Python標(biāo)準(zhǔn)庫(kù)自帶的,nose也曾風(fēng)靡一時(shí)。但pytest憑借其簡(jiǎn)潔的語(yǔ)法、強(qiáng)大的插件體系和豐富的斷言方式,成為了最受歡迎的選擇。

安裝pytest非常簡(jiǎn)單:

pip install pytest

驗(yàn)證安裝成功:

pytest --version

從一個(gè)簡(jiǎn)單函數(shù)開始

假設(shè)我們正在開發(fā)一個(gè)電商系統(tǒng),需要一個(gè)計(jì)算訂單折扣的函數(shù)。業(yè)務(wù)規(guī)則是:滿1000元打9折,滿500元打95折,會(huì)員額外享受折上9.5折。

# discount.py
def calculate_discount(amount, is_member=False):
    if amount < 0:
        raise ValueError("金額不能為負(fù)數(shù)")
    
    discount_rate = 1.0
    if amount >= 1000:
        discount_rate = 0.9
    elif amount >= 500:
        discount_rate = 0.95
    
    if is_member:
        discount_rate *= 0.95
    
    return round(amount * discount_rate, 2)

第一個(gè)測(cè)試用例

在同一個(gè)目錄下創(chuàng)建測(cè)試文件,pytest會(huì)自動(dòng)發(fā)現(xiàn)以test_開頭或結(jié)尾的文件。

# test_discount.py
import pytest
from discount import calculate_discount

def test_normal_customer_no_discount():
    """普通用戶未達(dá)到折扣門檻"""
    assert calculate_discount(300) == 300

def test_normal_customer_500_discount():
    """普通用戶滿500打95折"""
    assert calculate_discount(500) == 475.0
    assert calculate_discount(800) == 760.0

def test_normal_customer_1000_discount():
    """普通用戶滿1000打9折"""
    assert calculate_discount(1000) == 900.0
    assert calculate_discount(1500) == 1350.0

運(yùn)行測(cè)試:

pytest test_discount.py -v

-v參數(shù)讓輸出更詳細(xì)。看到綠色的點(diǎn),表示測(cè)試通過。

異常測(cè)試

測(cè)試不僅要驗(yàn)證正常情況,還要驗(yàn)證異常情況。pytest提供了簡(jiǎn)潔的異常斷言:

def test_negative_amount():
    """測(cè)試金額為負(fù)數(shù)時(shí)拋出異常"""
    with pytest.raises(ValueError, match="金額不能為負(fù)數(shù)"):
        calculate_discount(-100)

參數(shù)化測(cè)試

寫測(cè)試時(shí),我們經(jīng)常需要測(cè)試多組數(shù)據(jù)。手動(dòng)寫多個(gè)測(cè)試函數(shù)既冗余又難維護(hù)。pytest的參數(shù)化功能完美解決這個(gè)問題:

@pytest.mark.parametrize("amount, is_member, expected", [
    (300, False, 300),      # 普通用戶,無(wú)折扣
    (500, False, 475.0),    # 普通用戶,500檔
    (1000, False, 900.0),   # 普通用戶,1000檔
    (300, True, 300 * 0.95), # 會(huì)員,無(wú)門檻折扣
    (500, True, 500 * 0.95 * 0.95),  # 會(huì)員,500檔疊加會(huì)員折扣
    (1000, True, 1000 * 0.9 * 0.95), # 會(huì)員,1000檔疊加會(huì)員折扣
])
def test_discount_cases(amount, is_member, expected):
    """參數(shù)化測(cè)試多種場(chǎng)景"""
    assert calculate_discount(amount, is_member) == expected

這樣,一組數(shù)據(jù)就是一個(gè)測(cè)試用例。增加測(cè)試數(shù)據(jù)只需要在列表中追加,不需要新增函數(shù)。

固件(Fixture)的妙用

實(shí)際項(xiàng)目中,測(cè)試往往需要準(zhǔn)備復(fù)雜的測(cè)試數(shù)據(jù)。比如測(cè)試用戶訂單,需要?jiǎng)?chuàng)建用戶、商品、庫(kù)存、優(yōu)惠券等。如果每個(gè)測(cè)試函數(shù)都重復(fù)這些準(zhǔn)備工作,代碼會(huì)變得臃腫。

pytest的fixture解決了這個(gè)問題:

import pytest
from datetime import datetime, timedelta

@pytest.fixture
def sample_user():
    """創(chuàng)建一個(gè)測(cè)試用戶"""
    return {
        "id": 1,
        "name": "測(cè)試用戶",
        "is_member": True,
        "join_date": datetime.now() - timedelta(days=30)
    }

@pytest.fixture
def sample_order():
    """創(chuàng)建一個(gè)測(cè)試訂單"""
    return {
        "id": 1001,
        "items": [
            {"product_id": 1, "name": "商品A", "price": 299, "quantity": 2},
            {"product_id": 2, "name": "商品B", "price": 199, "quantity": 1}
        ],
        "total_amount": 797
    }

def test_order_with_member_discount(sample_user, sample_order):
    """測(cè)試會(huì)員訂單折扣"""
    user = sample_user
    order = sample_order
    # 計(jì)算折扣后的金額
    discounted = calculate_discount(order["total_amount"], user["is_member"])
    expected = 797 * 0.95  # 會(huì)員95折
    assert discounted == expected

fixture的強(qiáng)大之處在于它可以自動(dòng)管理資源的創(chuàng)建和清理,可以設(shè)置作用域(function、class、module、session),還可以相互依賴。

模擬(Mock)外部依賴

實(shí)際開發(fā)中,函數(shù)往往會(huì)調(diào)用外部服務(wù)——數(shù)據(jù)庫(kù)、API、文件系統(tǒng)等。測(cè)試時(shí)需要隔離這些依賴,讓測(cè)試既快速又可靠。

假設(shè)我們的折扣函數(shù)需要調(diào)用會(huì)員積分服務(wù):

def calculate_discount_with_points(amount, user_id):
    """根據(jù)用戶積分計(jì)算折扣"""
    points = get_user_points(user_id)  # 調(diào)用外部API
    if points > 1000:
        discount = 0.8
    elif points > 500:
        discount = 0.9
    else:
        discount = 1.0
    return amount * discount

測(cè)試時(shí),我們不希望真的調(diào)用積分服務(wù)。使用pytest-mock插件(基于unittest.mock):

def test_discount_with_points(mocker):
    """模擬積分服務(wù)返回值"""
    # 模擬get_user_points函數(shù)返回固定值
    mocker.patch('discount.get_user_points', return_value=600)
    
    from discount import calculate_discount_with_points
    result = calculate_discount_with_points(1000, 123)
    assert result == 900  # 600積分,打9折

測(cè)試覆蓋率

寫了測(cè)試,如何知道測(cè)了多少代碼?pytest-cov插件可以統(tǒng)計(jì)測(cè)試覆蓋率:

pip install pytest-cov
pytest --cov=discount test_discount.py --cov-report=html

這條命令會(huì)生成HTML格式的覆蓋率報(bào)告,直觀展示哪些代碼被測(cè)試覆蓋,哪些沒有。

持續(xù)集成中的pytest

測(cè)試只有持續(xù)運(yùn)行才有意義。配置CI/CD流水線,每次代碼提交自動(dòng)運(yùn)行測(cè)試:

# .github/workflows/test.yml
name: Run tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.9'
      - name: Install dependencies
        run: |
          pip install pytest pytest-cov
          pip install -r requirements.txt
      - name: Run tests
        run: pytest --cov=./ --cov-report=xml

測(cè)試分層策略

回到小王的故事。他的團(tuán)隊(duì)代碼混亂,測(cè)試無(wú)從下手。我建議他采用測(cè)試金字塔策略:

單元測(cè)試:測(cè)試單個(gè)函數(shù)、類。用mock隔離依賴,追求快速執(zhí)行。覆蓋率目標(biāo)80%以上。

集成測(cè)試:測(cè)試模塊間的交互,如數(shù)據(jù)庫(kù)操作、API調(diào)用??梢杂脺y(cè)試數(shù)據(jù)庫(kù),每次測(cè)試后回滾。

端到端測(cè)試:模擬用戶操作,測(cè)試完整業(yè)務(wù)流程。運(yùn)行最慢,數(shù)量最少。

# 集成測(cè)試示例
@pytest.fixture
def test_db():
    """創(chuàng)建測(cè)試數(shù)據(jù)庫(kù)連接"""
    db = create_test_database()
    yield db
    db.cleanup()  # 測(cè)試后清理

def test_save_order_to_database(test_db):
    """測(cè)試訂單保存到數(shù)據(jù)庫(kù)"""
    order = create_sample_order()
    order_id = test_db.save_order(order)
    saved_order = test_db.get_order(order_id)
    assert saved_order.total_amount == order.total_amount

實(shí)際項(xiàng)目中的pytest配置

大型項(xiàng)目中,pytest配置文件很有用。創(chuàng)建pytest.ini

[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
markers = 
    slow: 運(yùn)行較慢的測(cè)試
    integration: 集成測(cè)試
    smoke: 冒煙測(cè)試
addopts = -v --strict-markers --tb=short

使用標(biāo)記運(yùn)行特定測(cè)試:

pytest -m "not slow"  # 跳過慢測(cè)試
pytest -m "smoke"     # 只跑冒煙測(cè)試

處理測(cè)試數(shù)據(jù)

測(cè)試數(shù)據(jù)管理是個(gè)常見痛點(diǎn)。pytest-datadir插件幫助管理測(cè)試文件:

def test_import_data(datadir):
    """使用datadir中的測(cè)試文件"""
    csv_file = datadir / 'test_data.csv'
    data = read_csv(csv_file)
    assert len(data) == 10

并發(fā)測(cè)試

測(cè)試多了,運(yùn)行時(shí)間變長(zhǎng)。pytest-xdist實(shí)現(xiàn)并發(fā)測(cè)試:

pip install pytest-xdist
pytest -n auto  # 自動(dòng)使用所有CPU核心

失敗重試

網(wǎng)絡(luò)不穩(wěn)定的測(cè)試環(huán)境,可以用pytest-rerunfailures自動(dòng)重試失敗用例:

pip install pytest-rerunfailures
pytest --reruns 3 --reruns-delay 1

從0到1建立測(cè)試體系

三個(gè)月后,小王團(tuán)隊(duì)的測(cè)試覆蓋率從5%提升到了78%。他們是怎么做到的?

從核心邏輯開始:先為業(yè)務(wù)核心的函數(shù)編寫單元測(cè)試,這類代碼改動(dòng)頻繁,測(cè)試收益最高。

修復(fù)bug先加測(cè)試:遇到bug,先寫一個(gè)會(huì)失敗的測(cè)試用例,再修復(fù)代碼。這樣既驗(yàn)證了修復(fù),又防止回歸。

測(cè)試代碼也是代碼:保持測(cè)試代碼整潔,像生產(chǎn)代碼一樣review。復(fù)雜的測(cè)試邏輯同樣需要注釋。

不追求100%覆蓋率:覆蓋率是參考,不是目標(biāo)。UI層、第三方集成等代碼測(cè)試成本高,可以適當(dāng)放低要求。

結(jié)語(yǔ)

測(cè)試不是額外的工作,而是開發(fā)的一部分。pytest讓測(cè)試變得如此簡(jiǎn)單,以至于你會(huì)有寫測(cè)試的沖動(dòng)。

現(xiàn)在的小王,下班前運(yùn)行一下測(cè)試,看到一片綠色,安心地關(guān)掉電腦。即使凌晨被叫起來(lái),他也能自信地說:“測(cè)試都通過了,問題不在我們這邊。”

自動(dòng)化測(cè)試不能消滅所有bug,但能讓你睡個(gè)安穩(wěn)覺。從今天開始,用pytest給你的代碼上份保險(xiǎn)吧。

以上就是Python結(jié)合Pytest打造自動(dòng)化測(cè)試體系的詳細(xì)內(nèi)容,更多關(guān)于Python Pytest自動(dòng)化測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

靖宇县| 河源市| 麻江县| 邻水| 哈密市| 乳源| 双鸭山市| 绥中县| 儋州市| 吐鲁番市| 东安县| 类乌齐县| 伊吾县| 唐山市| 安岳县| 忻州市| 河北区| 琼结县| 黄陵县| 怀化市| 阳泉市| 武山县| 平武县| 米脂县| 清涧县| 洪雅县| 丰顺县| 巴彦县| 安陆市| 那坡县| 横峰县| 独山县| 达日县| 稷山县| 迁西县| 炉霍县| 卫辉市| 齐河县| 鸡泽县| 平昌县| 大冶市|