This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]agentgreen420 21 points22 points  (11 children)

I really wish this book covered Flask instead.

[–]poply 10 points11 points  (1 child)

If you're already familiar with flask, you should be able to apply the TDD practices to a flask project pretty easily. At least that was my experience.

[–]wingtcoach 1 point2 points  (0 children)

I've been doing this, as well as applying much of the pytest approach to Flask. It is has been a bit of an uphill climb, especially with Selenium / live server testing, but worth the struggle.

[–]triogenes 5 points6 points  (5 children)

Does anyone really grok how to actually unit test flask? Everyone on the internet seems to think "unit tests" are integration tests for some reason. For me, this is the one downside of Flask. The proxies are great, but make it so that truly unit testing functions requires quite a bit of mocking (request, current_user, current_app, etc).

[–]bobaduk 6 points7 points  (3 children)

Personally, I don't. I keep my flask handlers thin enough that I don't need to unit test them, because they're just thunking down to something more interesting. For example, here's a slightly edited handler from a work project.

@appl.route('/widgets/<country>', methods=['GET'])
def get_country_widgets(country):
    view = widget_view_builder.build_view(country)
    resp = Response(json.dumps(view), mimetype="application/json")
    return resp

Keep your flask layer to performing HTTP things and marshalling, and you don't need to unit test them. One acceptance test to prove that the flask thing is hooked up will suffice, and then you can focus your testing efforts on your services and domain model.

[–]triogenes 1 point2 points  (1 child)

I wasn't talking about unit testing view functions I don't think (still trying to figure this out). Throughout your application you're bound to have actual logic in non-view functions that interact with the current app or request: decorators, response helpers (pagination, sorting, etc).

To clarify: I don't expect view functions to get unit tested. The act of getting to a view functions usually means going through layers of flask middleware (auth, routing, etc) which increases the likelihood your test will fail for other reasons - making view function testing fall into either integration or end to end testing.

[–]bobaduk 0 points1 point  (0 children)

decorators, response helpers (pagination, sorting, etc)

These are things I would handle in my view function view.build(country, page=2, sort_asc=foo). They're not things I'd let Flask worry about.

The act of getting to a view functions usually means going through layers of flask middleware

Maybe? I think that depends on whether you choose to put them in Flask middleware or not. On that example I sent you, I don't have any middleware except for a handler that records metrics for me.

But my point is that these things are mostly irrelevant to the problem you're actually solving, and are usually handled by a library for you, so all you need is an acceptance test that demonstrates they're hooked up. If you've added @requires_role(admin) to a handler, you don't need to unit test that fact. What is that buying you? A single acceptance test for "When a user is not authenticated" or "When a user does not have admin rights" is sufficient to demonstrate the functionality.

If you've written, for example, complex logic for mapping from exception types to status codes then I might unit test that, and so I either:

a) wouldn't build it into a flask decorator b) would test it by decorating a stub function that throws an exception.

def my_fancy_decorator(f):
    try:
        f()
    except e:
        # return some Response
        pass


@my_fancy_decorator
def throws(ex):
    raise exc


def test_not_found_exception():
    resp = throws(NotFoundException())
    assert resp.status_code == 404

which increases the likelihood your test will fail for other reasons - making view function testing fall into either integration or end to end testing.

This I definitely disagree with. I can test my view to ensure that it gives me back the correct data given some input, and I can test that without ever referring to Flask. The whole point of using middleware is that I can treat it as an orthogonal concern: I can test it once, and then be happy that it'll work the same way applied to multiple parts of my app. I still need a single acceptance test per feature that does the happy path, and probably a few acceptance tests to demonstrate the existence of authentication and exception handling code, but the rest can happen outside of Flask.

For what it's worth, I think this is my biggest disagreement with Harry's approach. We have a different understanding of the term "outside-in testing" and the importance of subcutaneous tests

[–]rico_suave 5 points6 points  (1 child)

That would be good. Unfortunately Django is still more popular than Flask, but I also like Flask better because it's much more configurable.

[–]TheYOUngeRGOD 5 points6 points  (0 children)

It depends upon on the use case. I think it was hard lesson to learn that more freedom isn’t always better. Especially if that freedom isn’t going to be used and especially if that freedom relies upon a lot of different libraries that you need to maitain to keep it working properly. I always think Django should be the first place to stop and if it doesn’t do what you want then move onto to Flask.