簡體   English   中英

pytest 每次迭代的新測試| for 循環 | 參數化夾具

[英]pytest new test for every iteration | for loop | parametrize fixture

基本上,我試圖對路由列表的每次迭代進行測試,以檢查與特定函數關聯的網頁是否返回有效的狀態代碼。

我想要一些類似的東西:

import pytest
from flask import url_for
from myflaskapp import get_app

@pytest.yield_fixture
def app():
    # App context and specific overrides for test env
    yield get_app()

@pytest.yield_fixture
def client(app):
    yield app.test_client()

@pytest.yield_fixture
def routes(app):
    routes = [
    'foo',
    'bar',
    # There's quite a lot of function names here
    ]
    with app.app_context():
        for n, route in enumerate(routes):
            routes[n] = url_for(route)
            # yield url_for(route) #NOTE: This would be ideal, but not allowed.
            # convert the routes from func names to actual routes
    yield routes

@pytest.mark.parametrize('route', routes)
def test_page_load(client, route):
    assert client.get(route.endpoint).status_code == 200

我讀到過,由於解釋/加載/執行順序方面的原因,您不能將參數化與夾具混合作為參數,但是,這在“最佳實踐”方面是如何解決的?

我看到了一個解決方案,您可以直接從函數生成測試,這似乎非常靈活,可能符合我想要的在參數化中傳遞 pytest 夾具(雖然我不能直接使用調用夾具裝飾的函數,所以可能不是)

雖然,我是 pytest 的新手,我很想看到更多關於如何在幾乎沒有限制的迭代中生成測試或執行多個測試的示例,同時堅持正確的 pytest 樣式和 DRY 原則。 (我知道conftest.py)

如果重要的話,我會優先考慮多功能性/實用性而不是適當的樣式。 (在合理范圍內,可維護性也是重中之重)

我希望能夠參考此問題的解決方案,以幫助指導我將來如何解決構建測試的問題,但我似乎一直遇到障礙/限制,或者被 pytest 告知我無法按照我的方式執行 X 解決方案也期待/想要。

相關帖子:

  1. DRY: pytest:以 DRY 方式參數化裝置
  2. 從函數生成測試: 在參數化中傳遞 pytest 夾具
  3. 非常簡單的解決方案(不適用於這種情況): Parametrize pytest fixture
  4. PyTest 中的 Flask 應用上下文: 測試需要 Flask 應用或請求上下文的代碼
  5. 避免具有多個列表夾具的邊緣情況: 為什么 Pytest 對夾具參數執行嵌套循環

我目前摸索的解決方案是這樣的:

import pytest
from flask import url_for
from myflaskapp import get_app

@pytest.fixture
def app():
    app = get_app()
    # app context stuff trimmed out here
    return app

@pytest.fixture
def client(app):
    client = app.test_client()
    return client

def routes(app):
    '''GET method urls that we want to perform mass testing on'''
    routes = ['foo', 'bar']
    with app.app_context():
        for n, route in enumerate(routes):
            routes[n] = url_for(route)
    return routes

@pytest.mark.parametrize('route', routes(get_app()))
#NOTE: It'd be really nice if I could use routes as a 
# fixture and pytest would handle this for me. I feel like I'm
# breaking the rules here doing it this way. (But I don't think I actually am)
def test_page_load(client, route):
    assert client.get(route.endpoint).status_code == 200

我對這個解決方案的最大問題是,我不能直接將夾具作為函數調用,而這個解決方案要么需要那樣,要么在夾具之外完成我的夾具所做的所有工作,這並不理想。 我希望能夠參考這個解決方案來解決我將來如何構建我的測試。

對於任何希望專門復制我的 FLASK 解決方案的人:

我目前的解決方案對某些人來說可能比對我更糟糕,我的get_app()使用單例結構,所以如果在我的情況下多次調用get_app()應該get_app() ,因為它會調用create_app()和如果全局變量尚未定義,則將應用程序本身存儲為全局變量,基本上模擬僅調用一次create_app()的行為。

Pytest 固定裝置本身可以參數化,但不能使用pytest.mark.parametrize (看起來這種類型的問題也在這里得到了回答。)所以:

import pytest
from flask import url_for
from myflaskapp import get_app

@pytest.fixture
def app():
    app = get_app()
    # app context stuff trimmed out here
    return app

@pytest.fixture
def client(app):
    client = app.test_client()
    return client

@pytest.fixture(params=[
    'foo', 
    'bar'
])
def route(request, app):
    '''GET method urls that we want to perform mass testing on'''
    with app.app_context():
        return url_for(request.param)


def test_page_load(client, route):
    assert client.get(route.endpoint).status_code == 200

文檔是這樣解釋的:

Fixture 函數可以被參數化,在這種情況下,它們將被多次調用,每次執行一組相關測試,即依賴於該 Fixture 的測試。 測試函數通常不需要知道它們的重新運行。 夾具參數化有助於為組件編寫詳盡的功能測試,這些組件本身可以通過多種方式進行配置。

擴展前面的示例,我們可以標記夾具以創建兩個 smtp_connection 夾具實例,這將導致使用夾具的所有測試運行兩次。 Fixture 函數通過特殊的請求對象訪問每個參數:

 # content of conftest.py import pytest import smtplib @pytest.fixture(scope="module", params=["smtp.gmail.com", "mail.python.org"]) def smtp_connection(request): smtp_connection = smtplib.SMTP(request.param, 587, timeout=5) yield smtp_connection print("finalizing {}".format(smtp_connection)) smtp_connection.close()

主要的變化是使用@pytest.fixture 聲明參數,這是一個值列表,夾具函數將執行每個值,並且可以通過 request.param 訪問一個值。 無需更改測試功能代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM