python - Flask test_client() doesn't have request.authorization with pytest

Jony cruse picture Jony cruse · May 15, 2015 · Viewed 8k times · Source

I have problem when testing my flask app with pytest.
App is required basic auth which is parameters of request.authorization in flask.
But with pytest, flask.test_client() doesn't have request.authorization.

Here's a code of fixture:

@pytest.yield_fixture(scope='session')
def app()
    app = create_app()

    # some setup code

    ctx = app.app_context()
    ctx.push()
    yield app
    ctx.pop()
    # some teadown code

@pytest.fixture
def test_client(app)
     return app.test_client()

Here's a code of test:

def test_index(test_client):
    res = test_client.get("/", headers={"Authorization": "Basic {user}".format(user=b64encode(b"test_user"))})
    assert res.status_code == 200

When I run this test, I got this error:

E       assert 401 == 200
E        +  where 401 = <Response streamed [401 UNAUTHORIZED]>.status_code

Not only auth failure, but also request.authorization doesn't have any value(None).
Why this happen? Is there any solution?

Thanks.

Answer

Miguel picture Miguel · May 15, 2015

The credentials for HTTP Basic authentication must have a username and a password separated by a colon. If you're still using python 2, try this:

def test_index(test_client):
    credentials = b64encode(b"test_user:test_password")
    res = test_client.get("/", headers={"Authorization": "Basic {}".format(credentials)})
    assert res.status_code == 200

Python 3 is a little stricter about data sanity, so you have to make sure that the bytes are properly decoded before sending them to the server:

def test_index(test_client):
    credentials = b64encode(b"test_user:test_password").decode('utf-8')
    res = test_client.get("/", headers={"Authorization": f"Basic {credentials}"})
    assert res.status_code == 200