Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask Application Unit-Test Assertion Error

I've been long time reader, but this is my first time posting.

Ok, so I'm trying to unit test a demo application in Flask and I don't know what I'm doing wrong.

these are my "routes" in a file called manager.py:

@app.route('/')
@app.route('/index')
def hello():
    return render_template('base.html')


@app.route('/hello/<username>')
def hello_username(username):
    return "Hello %s" % username 

The first route is loading base.html template renders a "hi" message, which is working in the unit-test but the second route gets an assertion error.

and this is my testing file manage_test.py:

class ManagerTestCase(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def t_username(self, username):
        return self.app.post('/hello/<username>', follow_redirects=True)

    def test_username(self):
        rv = self.t_username('alberto')
        assert "Hello alberto" in rv.data

    def test_empty_db(self):
        rv = self.app.get('/')
        assert 'hi' in rv.data

This is the output from the unit-test run:

.F
======================================================================
FAIL: test_username (tests.manage_tests.ManagerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/albertogg/Dropbox/code/Python/flask-bootstrap/tests/manage_tests.py", line 15, in test_username
    assert "Hello alberto" in rv.data
AssertionError

----------------------------------------------------------------------
Ran 2 tests in 0.015s

FAILED (failures=1)

I want to know if you guys can help me! what am I doing wrong or missing?

EDIT

I did this and it's working

 
    class ManagerTestCase(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def t_username(self, username):
        return self.app.get('/hello/%s' % (username), follow_redirects=True')
        # either that or the Advanced string formatting from the answer are working.

    def test_username(self):
        rv = self.t_username('alberto')
        assert "Hello alberto" in rv.data

    def test_empty_db(self):
        rv = self.app.get('/')
        assert 'hi' in rv.data

like image 618
albertogg Avatar asked Dec 21 '12 05:12

albertogg


1 Answers

You should change your hello_username to the following:

@app.route('/hello/', methods=['POST'])
def hello_username():
    return "Hello %s" % request.form.get('username', 'nobody')

make sure to from flask import request also.

And an example, showing it working:

> curl -X POST -i 'http://localhost:2000/hello/' -d "username=alberto"
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 9
Server: Werkzeug/0.8.3 Python/2.7.2
Date: Fri, 21 Dec 2012 05:42:49 GMT

Hello alberto

And your test should look like:

def test_username(self, username):
    return self.app.post('/hello', data={"username":username})

EDIT
Per your comment:

@app.route('/hello/<username>', methods=['POST'])
def hello_username(username):
    print request.args
    return "Hello %s" % username

But, then I don't know why you would be using POST since this is essentially a POST without any POST body.

> curl -X POST -i 'http://localhost:2000/hello/alberto'           
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 13
Server: Werkzeug/0.8.3 Python/2.7.2
Date: Fri, 21 Dec 2012 06:29:25 GMT

Hello alberto

In that case, I would remove the requirement for POST data all together:

@app.route('/hello/<username>', methods=['POST'])
def hello_username(username):
    print request.args
    return "Hello %s" % username


> curl -i 'http://localhost:2000/hello/alberto'           
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 13
Server: Werkzeug/0.8.3 Python/2.7.2
Date: Fri, 21 Dec 2012 06:31:10 GMT

The test using GET would be

def test_username(self, username):
    return self.app.get('/hello/%s' % (username), follow_redirects=True)

Or, assuming you have 2.6+,

def test_username(self, username):
    return self.app.get('/hello/{username}'.format(username=username), follow_redirects=True)
like image 200
sberry Avatar answered Oct 22 '22 00:10

sberry