falconry / falcon

The no-magic web data plane API and microservices framework for Python developers, with a focus on reliability, correctness, and performance at scale.
https://falcon.readthedocs.io/en/stable/
Apache License 2.0
9.51k stars 937 forks source link

Prevent Pytest from collecting tests from falcon.testing.TestClient #2147

Closed aryaniyaps closed 1 year ago

aryaniyaps commented 1 year ago

Let us consider we have a test case like the following:

import pytest
from falcon import App, HTTP_200
from falcon.testing import TestClient

from app import create_app

@pytest.fixture(scope="session")
def app() -> App:
    """
    Initialize the app for testing.

    :return: The initialized app.
    """
    return create_app()

@pytest.fixture
def client(app: App) -> TestClient:
    return TestClient(app)

def test_get_books(client: TestClient) -> None:
    books = [
        {
            "name": "Life of Pi",
            "author_name": "Yann Martel",
            "isbn_code": "",
            "created_at": "",
            "updated_at": ""                
        },
        {
            "name": "Secret Six",
            "author_name": "Enid Blyton",
            "isbn_code": "",
            "created_at": "",
            "updated_at": ""                
        }
    ]
    response = client.simulate_get("/books")
    # result = json.loads(response)

    assert response.json == books
    assert response.status == HTTP_200

Notice that we are type hinting the test_get_books function. Because of this (and the fact that this test function lies in another file), pytest attempts to collect tests from TestClient (as the class name starts with "Test").

error traceback:

(server) PS C:\Users\iyapp\OneDrive\Desktop\web-projects\library\server> pytest tests
================================================================================================================================================ test session starts ================================================================================================================================================
platform win32 -- Python 3.10.2, pytest-7.2.2, pluggy-1.0.0
rootdir: C:\Users\iyapp\OneDrive\Desktop\web-projects\library\server
collected 1 item

tests\books\test_routes.py .                                                                                                                                                                                                                                                                                   [100%]

================================================================================================================================================= warnings summary ================================================================================================================================================== 
..\..\..\..\..\.virtualenvs\server-vNBXVCHh\lib\site-packages\falcon\testing\client.py:1898
  C:\Users\iyapp\.virtualenvs\server-vNBXVCHh\lib\site-packages\falcon\testing\client.py:1898: PytestCollectionWarning: cannot collect test class 'TestClient' because it has a __init__ constructor (from: tests/books/test_routes.py)
    class TestClient:

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

This is a known issue, and can be fixed by setting:

Testclient.__test__ = False

This is being done already by other frameworks such as starlette: https://github.com/encode/starlette/blob/master/starlette/testclient.py#L363

I think that the TestClient class must be updated to provide similar behavior.

CaselIT commented 1 year ago

Hi,

Thanks for reporting, do you have some reference about __test__ = False from pytest?

aryaniyaps commented 1 year ago

Hi,

Thanks for reporting, do you have some reference about __test__ = False from pytest?

yes, its a part of the nose idioms that pytest supports. https://docs.pytest.org/en/stable/how-to/nose.html#supported-nose-idioms

CaselIT commented 1 year ago

Thanks!