0

I have a CRUD football player flask app using SQL Alchemy and postgresql. I'm trying to test it with unittest and flask-testing but when I test delete and patch request on a player (based on his number), the statut returned is 200 but the player isn't deleted from the database so the test fail.

My app.py :

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='postgresql://postgres:password@localhost:5432/flask-sql-alchemy'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
modus = Modus(app)


class om_player(db.Model):

    __tablename__ = "players"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    number = db.Column(db.Integer)
    age = db.Column(db.Integer)

    def __init__(self, name, number, age):
        self.name = name
        self.number = number
        self.age = age

@app.route('/joueurs/<int:number>', methods=["GET", "PATCH", "DELETE"])
def show(number):
    found_player = om_player.query.filter_by(number=number).first()

    if request.method == b"PATCH":
        found_player.name = request.form['name']
        found_player.number = request.form['number']
        found_player.age = request.form['age']
        db.session.add(found_player)
        db.session.commit()
        return redirect(url_for('show', number=request.form['number']))
    if request.method == b"DELETE":
        db.session.delete(found_player)
        db.session.commit()
        return redirect(url_for('joueurs'))
    return render_template('show.html', player=found_player)

My test.py:

from app import app,db, om_player
from flask_testing import TestCase
import unittest

class BaseTestCase(TestCase):
    def create_app(self):
        app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password@localhost:5432/flask-sql-alchemy'
        app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False
        return app

    def test_delete(self):
        response = self.client.delete('/joueurs/18', follow_redirects=True)
        self.assertEqual(response.status_code, 200)
        self.assertNotIn(b"AMAVI", response.data)


if __name__ == '__main__':
    unittest.main()

(joueurs means players in french)

When I run python test.py :

AssertionError: b'AMAVI' unexpectedly found in b'my edit.html file'

So the player with number 18 and named "AMAVI" is not deleted and I don't understand why since the delete request return 200 and my app is working fine in local server.

DevAb
  • 530
  • 6
  • 12

1 Answers1

1

If you're using Python3, b"PATCH" and b"DELETE" are no longer doing what you expect. Those tests are failing for "POST" and falling through to the default "GET" case.

Evaluate

"POST" == b"POST"

in a Python3 REPL for confirmation.

Dave W. Smith
  • 24,318
  • 4
  • 40
  • 46
  • Thanks, you found where the problem comes from, "POST" == b"POST" return False in my Python3 REPL. Without 'b' in my delete and update request the test work. But flask-modus return bytes literal, if I run my app without the 'b' I got redirected and the player isn't deleted. I tried to add if request.method == b"DELETE" or "DELETE" but my app still bug (players get deleted when I just want to update them...). Is there any solution to make both app and test working ? – DevAb Dec 28 '18 at 14:03
  • I took a quick peek at the flask-modus source, and don't see any indication that it would return bytes rather than a string, but if I missed something, try `if request.method in [b"DELETE", "DELETE"]`. – Dave W. Smith Dec 29 '18 at 03:42
  • I read it on my flask course : [crud-with-flask-course](https://www.rithmschool.com/courses/flask-fundamentals/crud-with-flask) but yeah I did not find it in flask-modus documentation either. Thanks a lot for your help, the app and test work perfectly now. – DevAb Dec 29 '18 at 19:26