Skip to content

Instantly share code, notes, and snippets.

@typehorror
Created November 20, 2012 01:14
Show Gist options
  • Save typehorror/4115311 to your computer and use it in GitHub Desktop.
Save typehorror/4115311 to your computer and use it in GitHub Desktop.
Here is my way of having fixture loaded within my unit-test. the data from the fixture will then be loaded in your DB instance and also available on the object through self.data
from flask import Flask, render_template
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
# Database
db = SQLAlchemy()
def create_app(config="config"):
# Init app and load config
app = Flask(__name__)
app.config.from_object(config)
# Error Handler
@app.errorhandler(404)
def not_found(error):
return render_template("404.html"), 404
# Importing blueprint
from app.identities.views import mod as identitiesModule
from app.comments.views import mod as commentsModule
# Registering blueprint
app.register_blueprint(identitiesModule)
app.register_blueprint(commentsModule)
# Initialize SQLAlchemy
db.init_app(app)
return app
# import the main config and overwrite some for unittest purpose
from config import *
TESTING = True # sometimes it helps to know we are in tests mode
SQLALCHEMY_DATABASE_URI = "sqlite://" # Use SQL memory DB
CSRF_ENABLED = False # We don't want CSRF for testing
from fixture import DataSet
from werkzeug import generate_password_hash
from ..models import User, Identity
from ..constants import ADMIN, ACTIVE, USER, NEW, INACTIVE
class IdentityData(DataSet):
class Admin:
role = ADMIN
status_id = ACTIVE
email = "admin@example.com"
password = generate_password_hash("password")
class NewUser:
role = USER
status_id = NEW
email = "roger@example.com"
password = generate_password_hash("password")
class ActiveUser:
role = USER
status_id = ACTIVE
email = "steve@example.com"
password = generate_password_hash("password")
class OtherActiveUser:
role = USER
status_id = ACTIVE
email = "other@example.com"
password = generate_password_hash("password")
class InactiveUser:
role = USER
status_id = INACTIVE
email = "robert@example.com"
password = generate_password_hash("password")
class UserData(DataSet):
class Robert:
name = "Robert"
identity = IdentityData.InactiveUser
class Roger:
name = "Roger"
identity = IdentityData.NewUser
class Steve:
name = "Steve"
identity = IdentityData.ActiveUser
class Chris:
name = "Chris"
identity = IdentityData.OtherActiveUser
class Anthony:
name = "Anthony"
identity = IdentityData.Admin
class Mike:
name = "Mike"
identity = IdentityData.Admin
all_data = [IdentityData, UserData]
env = {
"UserData": User,
"IdentityData": Identity,
}
from flask import url_for
from app.lib.testing import TestCase
from app.identities.models import Identity
# importing some other fixture form another fixture directory
from app.comments.tests import fixtures as comments_fixtures
from .fixtures import all_data, env
# merging the data (can be as many as you want)
env.update(comments_fixtures.env)
all_data += comments_fixtures.all_data
class TestAuth(TestCase):
datasets = all_data
env = env
reg_data = {
"email": "example@example.com",
"name": "john",
"password": "password",
"confirm": "password",
}
def test_registerExistingEmail(self):
reg_data = self.reg_data.copy()
reg_data["email"] = self.data.IdentityData.InactiveUser.email
response = self.client.post(url_for("identities.register"), data=reg_data)
self.assertStatus(response, 200)
assert "email already exists" in response.data
def test_emailRegister(self):
response = self.client.post(url_for("identities.register"),
data=self.reg_data)
self.assertStatus(response, 302)
assert Identity.query.filter_by(email=self.reg_data["email"]).first()
def test_inactiveLogin(self):
response = self.client.get(url_for("identities.login"))
self.assertStatus(response, 200)
login_data = {
"email": self.data.IdentityData.InactiveUser.email,
"password": "password",
}
response = self.client.post(url_for("identities.login"), data=login_data)
self.assertStatus(response, 200);
assert "Wrong email or password" in response.data
def test_login(self):
response = self.client.get(url_for("identities.login"))
self.assertStatus(response, 200)
login_data = {
"email": self.data.IdentityData.ActiveUser.email,
"password": "password",
}
response = self.client.post(url_for("identities.login"), data=login_data)
self.assertStatus(response, 302);
self.assertRedirects(response, url_for("identities.home"))
response = self.client.get(url_for("identities.home"))
self.assertStatus(response, 200);
from urlparse import urlparse
from flask.ext.testing import TestCase as _TestCase
from fixture import SQLAlchemyFixture
from app import db, create_app
class TestCase(_TestCase):
"""
Handle fixture loading on top of flask test case
"""
datasets = []
data = None
fixture = None
env = None
def tear_down(self):
pass
def set_up(self):
pass
def create_app(self):
return create_app(config='config_test')
def create_fixture(self):
return SQLAlchemyFixture(session=self.session, env=self.env)
def setUp(self):
self.session = db.create_scoped_session({'autocommit':True})
if self.datasets:
self.fixture = self.create_fixture()
db.create_all()
self.data = self.fixture.data(*self.datasets)
self.data.setup()
self.set_up()
def tearDown(self):
if self.datasets:
self.data.teardown()
db.session.remove()
db.drop_all()
self.tear_down()
# to simplify unittest some helper methods...
def login(self, email=None, password='password', ID=None):
"""
login user with an Identity instance or email address.
"""
if ID:
email = ID.email
return self.client.post('/identities/login/', data={
'email': email, 'password': password})
def assertPath(self, response, path):
"""
ignore the query(?foo=bar) part of the response
"""
self.assertTrue(urlparse(response.location).path, path)
def assertExist(self, model, **kwargs):
"""
Assert existence of an object in the db
usage: assertExist(Identity, email="johndoe@example.com", status=1)
"""
self.assertIsNotNone(model.query.filter_by(**kwargs).first())
def assertNotExist(self, model, **kwargs):
"""
Check none existence of an object in the db
usage: assertNotExist(Identity, email="johndoe@example.com")
"""
self.assertIsNone(model.query.filter_by(**kwargs).first())
@typehorror
Copy link
Author

directory structure:

/config.py # main config
/config_test.py # config loaded when unittest on
/manage.py # using flask script
/app/__init__.py (contains create_app())
/app/identities/(__init__.py|views.py|forms.py|models.py...)
/app/identities/tests/fixtures.py
/app/identities/tests/test_auth.py

I use discover to run all my test at once. when I want to run just one test:

To run all the tests in TestAuth

python -m unittest app.identities.tests.test_auth.TestAuth

To run just test_registerExistingEmail test in TestAuth

python -m unittest app.identities.tests.test_auth.TestAuth.test_registerExistingEmail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment