librelist archives

« back to archive

Giving context to test_client()

Giving context to test_client()

From:
Jack Pearkes
Date:
2012-07-01 @ 17:41
Hello,

I'm currently working on tests for an authenticated endpoint, and am
using flask-login to keep things simple.

Behavior works in the browser as expected, but it seems like the
test_client is not using the context that I have set with flask-login.

def test_create_endpoint(self, user):
    """
    Checks to see if the create endpoint creates an object.
    """
    with app.test_request_context():

        # A flask-login method that takes a user object and sets the
necessary session cookies.
        login_user(user)

        # Post to the endpoint with the Flask test_client
        rv = app.test_client().post('/create/object')

        # The test apparently has the right context, as I can assert
the cookie set by flask-login
        assert session['user_id'] == '1'

        # The failing assertion
        assert rv._status_code == 200


Is there any way to give the test_client the context that I have in
the test, or a better way to go about this as whole?

Here's the endpoint, test and stacktrace:
https://gist.github.com/a25e7df6d06adf627485

Thanks!

Jack

Re: [flask] Giving context to test_client()

From:
Simon Sapin
Date:
2012-07-01 @ 17:48
Le 01/07/2012 19:41, Jack Pearkes a écrit :
> Is there any way to give the test_client the context that I have in
> the test

In short, no.

The test client goes through all the normal cycle to make requests on 
the application. It starts at the WSGI level to avoid going through the 
network, but it is otherwise just like a browser. On of the first steps 
of Flask’s request cycle is to create a new request context which will 
mask any previous context.


>, or a better way to go about this as whole?

Make a request to login just like a browser would. I think think the 
client will do the right thing and take care of cookies between 
subsequent calls with the same 'client' object.


Regards,
-- 
Simon Sapin

Re: [flask] Giving context to test_client()

From:
Jack Pearkes
Date:
2012-07-06 @ 05:32
Thanks Simon,

On Sun, Jul 1, 2012 at 10:48 AM, Simon Sapin <simon.sapin@exyr.org> wrote:
> Le 01/07/2012 19:41, Jack Pearkes a écrit :
>> Is there any way to give the test_client the context that I have in
>> the test
>
> In short, no.
>
> The test client goes through all the normal cycle to make requests on
> the application. It starts at the WSGI level to avoid going through the
> network, but it is otherwise just like a browser. On of the first steps
> of Flask’s request cycle is to create a new request context which will
> mask any previous context.
>
>
>>, or a better way to go about this as whole?
>
> Make a request to login just like a browser would. I think think the
> client will do the right thing and take care of cookies between
> subsequent calls with the same 'client' object.

This put me in the right direction. I ended up using Ghost.py to
emulate a browser, and it has been working well so far!

http://jeanphix.me/Ghost.py/

Thanks for the help,

Jack

>
>
> Regards,
> --
> Simon Sapin
>
>

Re: [flask] Giving context to test_client()

From:
Simon Sapin
Date:
2012-07-06 @ 05:56
Le 06/07/2012 07:32, Jack Pearkes a écrit :
> This put me in the right direction. I ended up using Ghost.py to
> emulate a browser, and it has been working well so far!
>
> http://jeanphix.me/Ghost.py/

Ghost uses a full WebKit engine and makes requests through the network 
stack (localhost as is may be.)

Unless you need to test JavaScript or other client-heavy code, it is 
just overkill in my opinion. What I had in mind was to use Flask’s test 
client:

     client = my_flask_app.test_client()

     # We’re not logged in yet
     rv = client.get('/admin')
     assert rv.status_code == 401  # Unauthorized

     # The 'data' dict here should mirror your HTML form
     rv = client.post('/login', data={user='alice', password='secret'})
     assert rv.status_code == 200
     # Other tests on the successful login page...

     # Now we should be logged in
     rv = client.get('/admin')
     assert rv.status_code == 200
     # Other tests...

The test client handles cookies (if you reuse the same `client` object) 
and redirects for you, but makes requests at the WSGI level. It’s only 
Python calls, without going through the network. It is much more 
lightweight than embedding a full browser engine.

Regards,
-- 
Simon Sapin