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

Python結(jié)合Pytest打造自動化測試體系

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

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

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

為什么是pytest

Python的測試框架不止一個,unittest是Python標準庫自帶的,nose也曾風(fēng)靡一時。但pytest憑借其簡潔的語法、強大的插件體系和豐富的斷言方式,成為了最受歡迎的選擇。

安裝pytest非常簡單:

pip install pytest

驗證安裝成功:

pytest --version

從一個簡單函數(shù)開始

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

# discount.py
def calculate_discount(amount, is_member=False):
    if amount < 0:
        raise ValueError("金額不能為負數(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)

第一個測試用例

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

# test_discount.py
import pytest
from discount import calculate_discount

def test_normal_customer_no_discount():
    """普通用戶未達到折扣門檻"""
    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

運行測試:

pytest test_discount.py -v

-v參數(shù)讓輸出更詳細??吹骄G色的點,表示測試通過。

異常測試

測試不僅要驗證正常情況,還要驗證異常情況。pytest提供了簡潔的異常斷言:

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

參數(shù)化測試

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

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

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

固件(Fixture)的妙用

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

pytest的fixture解決了這個問題:

import pytest
from datetime import datetime, timedelta

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

@pytest.fixture
def sample_order():
    """創(chuàng)建一個測試訂單"""
    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):
    """測試會員訂單折扣"""
    user = sample_user
    order = sample_order
    # 計算折扣后的金額
    discounted = calculate_discount(order["total_amount"], user["is_member"])
    expected = 797 * 0.95  # 會員95折
    assert discounted == expected

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

模擬(Mock)外部依賴

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

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

def calculate_discount_with_points(amount, user_id):
    """根據(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

測試時,我們不希望真的調(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折

測試覆蓋率

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

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

這條命令會生成HTML格式的覆蓋率報告,直觀展示哪些代碼被測試覆蓋,哪些沒有。

持續(xù)集成中的pytest

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

# .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

測試分層策略

回到小王的故事。他的團隊代碼混亂,測試無從下手。我建議他采用測試金字塔策略:

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

集成測試:測試模塊間的交互,如數(shù)據(jù)庫操作、API調(diào)用。可以用測試數(shù)據(jù)庫,每次測試后回滾。

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

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

def test_save_order_to_database(test_db):
    """測試訂單保存到數(shù)據(jù)庫"""
    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

實際項目中的pytest配置

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

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

使用標記運行特定測試:

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

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

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

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

并發(fā)測試

測試多了,運行時間變長。pytest-xdist實現(xiàn)并發(fā)測試:

pip install pytest-xdist
pytest -n auto  # 自動使用所有CPU核心

失敗重試

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

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

從0到1建立測試體系

三個月后,小王團隊的測試覆蓋率從5%提升到了78%。他們是怎么做到的?

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

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

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

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

結(jié)語

測試不是額外的工作,而是開發(fā)的一部分。pytest讓測試變得如此簡單,以至于你會有寫測試的沖動。

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

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

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

相關(guān)文章

最新評論

绵竹市| 张家川| 大同市| 隆子县| 眉山市| 馆陶县| 松江区| 祁门县| 吕梁市| 新密市| 东城区| 松阳县| 东阿县| 抚顺市| 太保市| 平泉县| 伊吾县| 舟山市| 乌审旗| 阿瓦提县| 蓝山县| 远安县| 阳朔县| 高唐县| 阳信县| 扶风县| 阆中市| 土默特右旗| 巫溪县| 都昌县| 建平县| 维西| 中山市| 宣武区| 中卫市| 阿拉善盟| 巩留县| 潞西市| 菏泽市| 买车| 武义县|