I have a working web application on Flask with SqlAlchemy for moderation of news, it has some api methods to handle moderation requests, such as approve, deny currently selected news, list them, etc. I want to write unit tests to this methods, and I made them work, but I don't understand, how to implement executing all requests which I do from test cases in one db session, so that I could remove all changes to database. Or is there another cleaner or proper way to do this? I've found out that maybe all I need is "scoped_session" in SqlAlchemy, but all my attemts to implement it have failed. If that's correct way, please, tell me where to use this lines of code (in settings, or in test case set_up method).
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker session_factory = sessionmaker() Session = scoped_session(session_factory)
I suggest you use the Flask-Testing extension. This is an approved extension which lets you do the unit testing as you desire. It has a specific section for SQLAlchemy as well.
Testing with SQLAlchemy
This covers a couple of points if you are using Flask-Testing with SQLAlchemy. It is assumed that you are using the Flask-SQLAlchemy extension, but if not the examples should not be too difficult to adapt to your own particular setup.
First, ensure you set the database URI to something other than your production database ! Second, it’s usually a good idea to create and drop your tables with each test run, to ensure clean tests:"
from flask.ext.testing import TestCase from myapp import create_app, db class MyTest(TestCase): SQLALCHEMY_DATABASE_URI = "sqlite://" TESTING = True def create_app(self): # pass in test configuration return create_app(self) def setUp(self): db.create_all() def tearDown(self): db.session.remove() db.drop_all()
This is the way I've been running unit tests recently. I'm assuming since you are using SQLAlchemy that you're using model classes. I'm also assuming that all of your tables are defined as SQLAlchemy model classes.
from flask import Flask import unittest from app import db from app.models import Log from constants import test_logs class appDBTests(unittest.TestCase): def setUp(self): """ Creates a new database for the unit test to use """ self.app = Flask(__name__) db.init_app(self.app) with self.app.app_context(): db.create_all() self.populate_db() # Your function that adds test data. def tearDown(self): """ Ensures that the database is emptied for next unit test """ self.app = Flask(__name__) db.init_app(self.app) with self.app.app_context(): db.drop_all()
Since you're using the same DB set up as your app this allows you to build and destroy a test database with every unit test you run.