gpt4 book ai didi

Python Nose 测试、SQLAlchemy 和 "convenience functions"

转载 作者:行者123 更新时间:2023-12-01 04:49:15 26 4
gpt4 key购买 nike

我有一个问题,关于如何设计良好的 Nose 单元测试(使用每个测试事务和回滚),不仅围绕 SQLAlchemy 模型,而且围绕我编写的围绕 SQLAlchemy 模型创建的便利函数。

我对如何编写基本单元测试类有很好的理解,其中包括必要的设置和拆卸固定装置,以将所有测试包装在事务中,并在测试完成时回滚它们。然而,到目前为止,所有这些测试都涉及直接创建模型。例如,像这样测试用户模型(BaseTestCase 包含安装/拆卸装置):

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

但是,我还编写了一个方便的函数,它包含了 User 对象的创建。它处理各种事情,例如确认密码与验证密码匹配,然后创建盐、散列密码+盐等,然后将这些值放入用户表/对象的相关列/字段中。它看起来像这样:

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

现在,我也想对这个函数进行单元测试,但我不确定将其包装在单元测试用例中的正确方法,这些用例使用测试数据库实现,在每次测试后回滚事务等。

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
# Now how do I finangle things so the transaction
# executed by create_user is rolled back after the test?

预先感谢您的帮助,并为我指明了正确的方向。

最佳答案

这里有两种可能的方法:

在测试之间重新创建数据库

在您的 setUp() 代码中,从空白数据库开始,为您正在测试的对象创建所需的表。在 tearDown() 中,自行清理。

您可以创建一个基本测试类,例如:

class SqlaTestCase(unittest.TestCase):
db_url = 'sqlite:///:memory:'
auto_create_tables = True

def setUp(self):
self.engine = create_engine(self.db_url)
self.connection = self.engine.connect()

if self.auto_create_tables:
self.create_tables()

Session = sessionmaker(bind=self.connection)
self.session = Session()

def tearDown(self):
self.session.close_all()
if self.auto_create_tables:
self.drop_tables()
self.connection.close()
self.engine.dispose()

def create_tables(self):
self.Base.metadata.create_all(self.engine)

def drop_tables(self):
self.Base.metadata.drop_all(self.engine)

这样每个测试就不必担心留下提交的数据。

不要在不同级别重新测试相同的功能

如果您有良好的测试覆盖率,则此帮助程序调用的底层功能已经过测试。因此,您可以专注于确保此级别的逻辑正确。

模拟 session (甚至密码散列功能)并进行测试以确保进行适当的调用(例如 assert_ Called_with())。

关于Python Nose 测试、SQLAlchemy 和 "convenience functions",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28769357/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com