How do you set up a Flask application with SQLAlchemy for testing?

前端 未结 3 1712
遇见更好的自我
遇见更好的自我 2020-12-24 12:47

It seems common practice in Flask to start like this:

from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
SQLALCHEMY_DAT         


        
3条回答
  •  半阙折子戏
    2020-12-24 13:13

    You won't want to make connecting to the db happen at import time. Go ahead and configure your app at import time because you can always tweak the configuration in your tests before attempting to test or run your app. In the example below you'll have your db connection behind some functions that use the application config so in a unittest you can actually change the db connection to point to a different file and then go ahead and connect explicitly in your setup.

    Say you have a myapp package containing myapp.py which looks like:

    # myapp/myapp.py
    from __future__ import with_statement
    from sqlite3 import dbapi2 as sqlite3
    from contextlib import closing
    from flask import Flask, request, session, g, redirect, url_for, abort, \
         render_template, flash
    
    # configuration
    DATABASE = '/tmp/flaskr.db'
    DEBUG = True
    SECRET_KEY = 'development key'
    USERNAME = 'admin'
    PASSWORD = 'default'
    
    # create our little application :)
    app = Flask(__name__)
    app.config.from_object(__name__)
    app.config.from_envvar('MYAPP_SETTINGS', silent=True)
    
    def connect_db():
        """Returns a new connection to the database."""
        return sqlite3.connect(app.config['DATABASE'])
    
    
    def init_db():
        """Creates the database tables."""
        with closing(connect_db()) as db:
            with app.open_resource('schema.sql') as f:
                db.cursor().executescript(f.read())
            db.commit()
    
    
    @app.before_request
    def before_request():
        """Make sure we are connected to the database each request."""
        g.db = connect_db()
    
    
    @app.after_request
    def after_request(response):
        """Closes the database again at the end of the request."""
        g.db.close()
        return response
    
    @app.route('/')
    def show_entries():
        cur = g.db.execute('select title, text from entries order by id desc')
        entries = [dict(title=row[0], text=row[1]) for row in cur.fetchall()]
        return render_template('show_entries.html', entries=entries)
    
    if __name__=="__main__":
        app.run()
    

    Your test file myapp/test_myapp.py will look like this:

    import os
    import myapp
    import unittest
    import tempfile
    
    class MyappTestCase(unittest.TestCase):
    
        def setUp(self):
            self.db_fd, myapp.app.config['DATABASE'] = tempfile.mkstemp()
            self.app = myapp.app.test_client()
            myapp.init_db()
    
        def tearDown(self):
            os.close(self.db_fd)
            os.unlink(myapp.app.config['DATABASE'])
    
        def test_empty_db(self):
            rv = self.app.get('/')
            assert 'No entries here so far' in rv.data
    

    Of course if you'd like to use SQLAlchemy you'll have to update the connect_db and init_db functions appropriately but hopefully you get the idea.

提交回复
热议问题