UNKNOWN
pip install Factory-Alchemist==0.1.1
Make it easier to create dummy entries in database in tests using SQLAlchemy
First you must have all models and session configured on you project
from sqlalchemy import create_engine, MetaData, Column, Integer, String, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///')
metadata = MetaData(bind=engine)
BaseModel = declarative_base(metadata=metadata)
Session = sessionmaker(bind=engine, autoflush=True, autocommit=True)
class Spam(BaseModel):
__tablename__ = 'spam'
id = Column(Integer, primary_key=True)
purpose = Column(String)
flavor = Column(Integer, nullable=False)
session = Session()
Second you must configure your base model on Factory Alchemist:
from factory_alchemist import factory
factory.BaseModel = BaseModel
Then you can start creating database entries:
from factory_alchemist import factory
spam_1 = factory.make(session, Spam)
spam_2 = factory.make(session, Spam, purpose='ham')
spam_3 = factory.make(session, Spam, flavor=7)
spam_1.id, spam_1.purpose, spam_1.flavor # 1, '<random string>', None
spam_2.id spam_2.purpose, spam_2.flavor # 2, 'ham', None
spam_3.id spam_3.purpose, spam_3.flavor # 3, '<random string>', 7
You can also create entries from sqlalchemy's table:
from factory_alchemist import factory
FishTable = Table('fish', metadata,
Column('id', Integer, primary_key=True),
Column('spam_id', Integer, ForeignKey('spam.id'), nullable=False))
my_fish = factory.make_t(FishTable)
my_fish.id, my_fish.spam_id # 1, 1
session.query(Spam).count() # 1
# Yes, it creates all mandatory foreign key entries!
Your tests may be something like this:
from unittest import TestCase
class MyTestCase(TestCase):
def setUp(self):
self.__rebuild_schema()
self.session = Session()
def tearDown(self):
self.session.close()
def test_something(self):
factory.make(self.session, Spam, purpose='dunno')
self.assertEqual([('dunno',)],
self.session.query(Spam.purpose).all())
def __rebuild_schema():
if 'sqlite' in metadata.bind.url.drivername:
metadata.drop_all()
metadata.create_all()
else:
raise Exception('Not running on SQLite. I am afraid of recreating the database')
Currently Factory Alchemist supports basic SQLAlchemy's field types
If you want/need to add other types, you can use the add_type
function.
import json
from sqlalchemy import String, TypeDecorator
from factory_alchemist import factory
from factory_alchemist.generators import rand_word
class Json(TypeDecorator):
impl = String
def process_bind_param(self, value, dialect):
return json.dumps(value)
def process_result_value(self, value, dialect):
return json.loads(value)
def generate_json(type_):
return {rand_word(10): rand_word(10)}
factory.add_type(Json, generate_json)
class Spam(BaseModel):
__tablename__ = 'spam'
my_field = Column(Json, nullable=False)
factory.make(session, Spam)
# <Spam (my_field={'dglwvkrkfn': 'tbcewysqwy'})>