From 71d309bb4e030e7eca3a2542a7d060bfd5fb8eca Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Sat, 7 Dec 2013 17:59:18 -0600 Subject: [PATCH] Add base DbTestCase --- README.rst | 5 ++-- .../{{cookiecutter.repo_name}}/database.py | 7 ++++++ .../{{cookiecutter.repo_name}}/tests/base.py | 25 +++++++++++++++++++ .../tests/test_models.py | 22 +++------------- 4 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 {{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/base.py diff --git a/README.rst b/README.rst index db2a0f0..a880335 100644 --- a/README.rst +++ b/README.rst @@ -65,10 +65,11 @@ Changelog 0.3.0 ***** -- "Divisional" organization: each blueprint contains its own view, models, and forms in a directory. There is still a single directory for templates and static assets. +- More modular organization: each blueprint contains its own view, models, and forms in a directory. There is still a single directory for templates and static assets. - Use Flask-Bcrypt for password hashing. -- Flask-Testing support. - Flask-Login for authentication. +- Simple test setup. Just create a subclass of ``DbTestCase``. +- Flask-Testing support. - Use Factory-Boy for test factories. 0.2.0 (09/21/2013) diff --git a/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/database.py b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/database.py index 98dd8d6..cf6877d 100644 --- a/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/database.py +++ b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/database.py @@ -6,6 +6,9 @@ mixins. from .extensions import db class CRUDMixin(object): + """Mixin that adds convenience methods for CRUD (create, read, update, delete) + operations. + """ __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) @@ -21,20 +24,24 @@ class CRUDMixin(object): @classmethod def create(cls, **kwargs): + '''Create a new record and save it the database.''' instance = cls(**kwargs) return instance.save() def update(self, commit=True, **kwargs): + '''Update specific fields of a record.''' for attr, value in kwargs.iteritems(): setattr(self, attr, value) return commit and self.save() or self def save(self, commit=True): + '''Save the record.''' db.session.add(self) if commit: db.session.commit() return self def delete(self, commit=True): + '''Remove the record from the database.''' db.session.delete(self) return commit and db.session.commit() diff --git a/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/base.py b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/base.py new file mode 100644 index 0000000..4f154e7 --- /dev/null +++ b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/base.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from flask.ext.testing import TestCase +from {{ cookiecutter.repo_name }}.settings import Config +from {{ cookiecutter.repo_name }}.app import create_app +from {{ cookiecutter.repo_name }}.database import db + + +class TestConfig(Config): + TESTING = True + DEBUG = True + SQLALCHEMY_DATABASE_URI = 'sqlite://' + + +class DbTestCase(TestCase): + """Base TestCase for tests that require a database.""" + + def create_app(self): + app = create_app(TestConfig) + with app.app_context(): + db.create_all() + return app + + def tearDown(self): + db.session.remove() + db.drop_all() diff --git a/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/test_models.py b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/test_models.py index ab1decb..1e620fa 100644 --- a/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/test_models.py +++ b/{{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}/tests/test_models.py @@ -1,28 +1,14 @@ # -*- coding: utf-8 -*- import unittest from nose.tools import * # PEP8 asserts -from flask.ext.testing import TestCase -from {{ cookiecutter.repo_name }}.app import create_app from {{ cookiecutter.repo_name }}.database import db from {{ cookiecutter.repo_name }}.user.models import User +from .base import DbTestCase from .factories import UserFactory -class TestUser(TestCase): - TESTING = True - DEBUG = True - SQLALCHEMY_DATABASE_URI = 'sqlite://' - - def create_app(self): - app = create_app(self) - with app.app_context(): - db.create_all() - return app - - def tearDown(self): - db.session.remove() - db.drop_all() +class TestUser(DbTestCase): def test_factory(self): user = UserFactory(password="myprecious") @@ -34,10 +20,8 @@ class TestUser(TestCase): assert_true(user.check_password("myprecious")) def test_check_password(self): - user = User(username="foo", email="foo@bar.com", + user = User.create(username="foo", email="foo@bar.com", password="foobarbaz123") - db.session.add(user) - db.session.commit() assert_true(user.check_password('foobarbaz123')) assert_false(user.check_password("barfoobaz"))