vendredi 27 février 2015

Python Nose tests, SQLAlchemy, and "convenience functions"

I have a question about how to design good Nose unit tests (using per test transactions and rollbacks) not just around SQLAlchemy models, but also around convenience functions I've written which surround the creation of SQLAlchemy models.


For example, I have a decent understanding of how to write a basic unit test class, which includes the necessary setup and teardown fixtures to wrap all of the tests in transactions, and roll them back when the test is complete. However, all of these tests so far involve directly creating models. For example, testing a User model like so (BaseTestCase contains setup/teardown fixtures):



from Business.Models import User

class test_User(BaseTestCase):

def test_user_stuff(self):
user = User(username, first_name, last_name, ....)
self.test_session.add(user)
self.test_session.commit()
# do various test stuff here, and then the
# transaction is rolled back after the test ends


However, I've also written a convenience function which wraps around the creation of a User object. It handles various things like confirming password matches verification password, then creating a salt, hashing password + salt, etc, and then putting those values into the relevant columns/fields of the User table/object. It looks something like this:



def create_user(username, ..., password, password_match):

if password != password_match:
raise PasswordMatchError()

try:
salt = generate_salt()
hashed_password = hash_password(password, salt)

user = User(username, ..., salt, hashed_password)
db_session.add(user)
db_session.commit()

except IntegrityError:
db_session.rollback()
raise UsernameAlreadyExistsError()

return user


There's obviously more to it than that, but that's the gist. Now, I'd like to unit test this function as well, but I'm not sure the correct way to wrap this in unit test cases which implement using a test database, rolling back transactions after every test, etc.



from Business.Models.User import create_user

class test_User(BaseTestCase):

def test_create_user_stuff(self):
user = create_user(username, first_name, last_name, ....)
# do various test stuff here, and then how do
# I finangle things so the transaction executed by
# create_user is rolled back after the test


Thanks in advance for the help, and pointing me in the right direction.


Aucun commentaire:

Enregistrer un commentaire