The following test code does not pass even though manually submitting the form on my web interface actually does work.

import os
from flask.ext.testing import TestCase
from flask import url_for

from config import _basedir
from app import app, db
from app.users.models import User


class TestUser(TestCase):

    def create_app(self):
        """
        Required method. Always implement this so that app is returned with context.
        """
        app.config['TESTING'] = True
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(_basedir, 'test.db')
        app.config['WTF_CSRF_ENABLED'] = False  # This must be disabled for post to succeed during tests
        self.client = app.test_client()
        ctx = app.app_context()
        ctx.push()
        return app

    def setUp(self):
        db.create_all()
        #pass

    @app.teardown_appcontext
    def tearDown(self):
        db.session.remove()
        db.drop_all()
        #pass

    def test_admin_home(self):

        # url is the admin home page
        url = url_for('admin.index')
        resp = self.client.get(url)
        self.assertTrue(resp.status_code == 200)

    def test_admin_registration(self):

        url = url_for('admin.register_view')
        data = {'username': 'admin', 'email': 'admin@example.com', 'password': 'admin'}
        resp = self.client.post(url, data)
        self.assertTrue(resp.status_code == 200)

        u = User.query.filter_by(username=u'admin').first()
        self.assertTrue(u.username == 'admin')   # <----- This fails. Why?

After the test client has post to the register_view url and returns a 200 OK response, I fail to retrieve the 'admin' user from the test database. Why is this so?

Here's the view code (this is a flask admin view)

from flask import request
from flask.ext.admin import expose, AdminIndexView, helpers

from app.auth.forms import LoginForm, RegistrationForm
from app.users.models import User
from app import db


class MyAdminIndexView(AdminIndexView):

    @expose('/', methods=('GET', 'POST'))
    def index(self):
        # handle user login
        form = LoginForm(request.form)
        self._template_args['form'] = form
        return super(MyAdminIndexView, self).index()

    @expose('/register/', methods=('GET', 'POST'))
    def register_view(self):
        # handle user registration
        form = RegistrationForm(request.form)
        if helpers.validate_form_on_submit(form):
            user = User()
            form.populate_obj(user)
            db.session.add(user)
            db.session.commit()

        self._template_args['form'] = form
        return super(MyAdminIndexView, self).index()
有帮助吗?

解决方案

Dumbest mistake ever.

The offending line in my test code is

resp = self.client.post(url, data)

It should be

resp = self.client.post(url, data=data)

I managed to track it down by painstakingly walking through the logic and inserting ipdb.set_trace() step by step until I found the bad POST request made by my client.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top