Python 如何使用pytest对sqlalchemy orm类进行单元测试
我想编写一些py.test代码来测试基于创建的2个简单的sqlalchemy ORM类。问题是,如何将py.test中的数据库设置为测试数据库,并在测试完成后回滚所有更改?是否可以模拟数据库并运行测试,而不实际连接到de数据库 以下是我的课程代码:Python 如何使用pytest对sqlalchemy orm类进行单元测试,python,python-3.x,sqlalchemy,pytest,Python,Python 3.x,Sqlalchemy,Pytest,我想编写一些py.test代码来测试基于创建的2个简单的sqlalchemy ORM类。问题是,如何将py.test中的数据库设置为测试数据库,并在测试完成后回滚所有更改?是否可以模拟数据库并运行测试,而不实际连接到de数据库 以下是我的课程代码: 从sqlalchemy导入创建_引擎,ForeignKey 从sqlalchemy.ext.declarative导入声明性基础 从sqlalchemy导入列,整数,字符串 从sqlalchemy.orm导入sessionmaker,关系 eng=
从sqlalchemy导入创建_引擎,ForeignKey
从sqlalchemy.ext.declarative导入声明性基础
从sqlalchemy导入列,整数,字符串
从sqlalchemy.orm导入sessionmaker,关系
eng=创建引擎('mssql+pymssql://user:pass@主机/我的_数据库')
Base=声明性_Base(英语)
会话=会话生成器(英语)
实习课程=课程()
类作者(基本):
__tablename_u=“作者”
AuthorId=列(整数,主键=True)
名称=列(字符串)
账簿=关系(“账簿”)
def添加_书(自我,标题):
b=书籍(标题=标题,AuthorId=self.AuthorId)
实习课程。添加(b)
intern_session.commit()
教材(基本):
__tablename_u=“图书”
BookId=列(整数,主键=True)
标题=列(字符串)
AuthorId=列(整数,ForeignKey(“Authors.AuthorId”))
作者=关系(“作者”)
我通常这样做:
Base=declarative_Base()
我只在需要时使用创建会话
engine=创建引擎(“”)
db_session=sessionmaker(bind=engine)
您也可以不使用add\u book
方法中的intern\u session
,而是使用session
参数
def添加书(自我、会话、标题):
b=书籍(标题=标题,AuthorId=self.AuthorId)
会议.添加(b)
session.commit()
它使您的代码更易于测试,因为您现在可以在调用该方法时通过您选择的会话。
而且,您不再需要绑定到硬编码数据库url的会话
--dburl
选项添加到pytest
只需将其添加到顶级的conftest.py
:
def pytest\u addoption(解析器):
parser.addoption('--dburl',
行动='商店',
默认值=“”,
help='要用于测试的数据库的url')
现在可以运行pytest--dburl
dburl
选项
- 从自定义装置:
@pytest.fixture() def db_url(请求): return request.config.getoption(“--dburl”) # ...
- 在测试中:
def测试(请求): db_url=request.config.getoption(“--dburl”) # ...
此时,您可以:
- 在任何测试或夹具中获取测试
db_url
- 使用它来创建引擎
- 创建绑定到引擎的会话
- 将会话传递给已测试的方法
从sqlalchemy导入创建引擎
从sqlalchemy.orm导入作用域的_会话,sessionmaker
@pytest.fixture(scope='session')
def db_发动机(请求):
“”“生成一个SQLAlchemy引擎,该引擎在测试会话后被抑制”“”
db_url=request.config.getoption(“--dburl”)
引擎=创建引擎(db\U url,echo=True)
屈服发动机_
引擎处理()
@pytest.fixture(scope='session')
def db_会话_工厂(db_发动机):
“”“返回SQLAlchemy作用域的会话工厂”“”
返回作用域_会话(sessionmaker(bind=db_引擎))
@pytest.fixture(scope='function')
def db_会话(db_会话工厂):
“”“生成测试后回滚的SQLAlchemy连接”“”
session=db\u session\u工厂()
收益期_
会话.回滚()
会话\结束()
使用db_会话
fixture,您可以为每个测试获得一个干净的db_会话
。
测试结束时,回滚
db\u会话
,保持数据库干净。Nice!它成功了,有没有办法使用pytest的fixture来模拟数据库?因此,测试不需要与数据库建立真正的连接,我可以测试所有方法是否工作正常。@Feulo使用pytest和库可能会使用假数据库模拟,但这是我从未做过的。我将查看unnitest.mock文档。谢谢使用此选项后,它似乎无法在测试期间处理session.commit调用,因为没有嵌套事务。这意味着测试可能会提交到数据库。我可能错了,因为我没有完全掌握一切。但这对我很有用:@Tryph如果您有一个从Base继承的中间接口呢?为了扩展SQLAlchemy ORM的一些功能。非常感谢!