bobwal
bobwal

Reputation: 542

Unit testing Flask function (with logged in user)

I'm new to Python and Flask but I'm gradually getting to grips with it. I've got so far into building an app and I'm now thinking I should start some unit testing. I really can't get my head around it though. I've read various docs, posts and examples but I can't seem to transfer this to my own code. I'm hoping if someone can show me how to write a test for one of my functions then things will fall into place. It's very tempting at this stage to ignore it and press on building my app.

@app.route('/user/<nickname>/create_bike', methods = ['GET', 'POST'] )
@login_required
def create_bike(nickname):
    user = User.query.filter_by(nickname = nickname).first()
    bikes = user.bikes.all()
    bikecount = user.bikes.count()
    form = CreateBike()
    if form.validate_on_submit():
        if bikecount < user.bike_allowance:
            # let user create a bike
            newbike = Bikes(bikename = form.bikename.data, 
                user_id = g.user.id, shared = SHARED )
            db.session.add(newbike)
            db.session.commit()
            flash('Your new bike has been created')
            return redirect(url_for('create_bike', nickname = nickname))
        else:
            flash("You have too many bikes")
    return render_template('create_bike.html',
        user = user,
        form = form
        )

UPDATE - Here's my working test

def test_create_bike(self):
    u = User(nickname = 'john', email = '[email protected]', account_type = "tester")
    db.session.add(u)
    db.session.commit()
    # login user
    with self.app as c:
        with c.session_transaction() as sess:
            sess['user_id'] = int(u.get_id())
            # http://pythonhosted.org/Flask-Login/#fresh-logins
            sess['_fresh'] = True
        rv = c.post('/user/john/create_bike', data = dict(
            bikename = 'your new bike',
            user_id = sess['user_id'],
            shared = 1
        ), follow_redirects = True)
        assert 'Your new bike has been created' in rv.data

Upvotes: 1

Views: 1625

Answers (2)

DazWorrall
DazWorrall

Reputation: 14210

Your test is likely failing because that view requires a logged in user, and since you arent passing in any session data, you are being redirected to the login page (the data argument to .post is form data, available in request.form in your view). Before your assertion you can see what the response is to help you along the way:

print rv.status_code
print rv.location #None if not a redirect

There's some documentation around sessions in tests here, and if you're using Flask-Login like it looks you are, this answer shows you how to set the session up so you get a logged in user

Upvotes: 2

raphonic
raphonic

Reputation: 341

You're on the right track.

Checking if the html page contains some piece of data that should be there is one the most common scenarios in testing web apps. You just need to repeat for all the other pages that you create. You can also add tests to see that creating a user follows all the validation rules that you've setup or that the username field is unique etc.

Upvotes: 0

Related Questions