【发布时间】:2017-04-18 23:11:00
【问题描述】:
我需要实例的 tearDownClass(cls) 方法。
我的意思是我可以引用 self(instance),而不是 cls(class)。
一种 tearDownTestCase(self)。
我的目的是在所有测试用例运行后清理数据库。
tearDown(self) 在每个测试结束时执行,我不想使用它。
tearDownClass(cls) 在所有测试完成时执行一次,但它不包含对 self 的引用,我需要访问 self 的属性(更准确地说是一个函数)。
有没有办法做到这一点?
Python 3.6
真实场景示例:
import unittest
'''
The real records saved in the database came from an external source (an API) so the ID is preassigned.
For the test I use everywhere a predefined fixed id, so the code result more clean.
'''
record_id = "TEST"
class RepositoryTest(unittest.TestCase):
def setUp(self):
# real initialization, reading connection string from config, database name, collection...
self.repository = None
# self._cleanup_record() # maybe here is executed too many unnecessary times
def tearDown(self):
# here is executed unnecessarily, because (where needed) the cleanup is eventually executed BEFORE the test (or in its beginning)
self._cleanup_record()
### pseudo (desired) method ###
def tearDownTestCase(self):
self._cleanup_record()
def tearDownClass(cls):
# self._cleanup_record() # self is not available
# rewrite the same code of initialization and _cleanup_record()
# I want to a void (or simplify this)
pass
# this is 1 of N tests
def test_save_record(self):
# cleanup (because I don't know in which state the database is)
self._cleanup_record() # almost every test require this, so it can be done in setUp()
# arrange
record = self._create_record()
# act
self.repository.save_record(record)
# assert
saved_record = self._get_record()
self.assertEquals(saved_record["my field"], record["my field"])
# utility methods
def _get_record(self):
# use self.repository and return the record with id = record_id
pass # return the record
def _create_record(self):
# use self.repository and create (and save) a record with id = record_id
return None # return the saved record
def _cleanup_record(self):
# use self.repository and delete the record with id = record_id (if exists)
pass
在 tearDown() 方法中进行清理会导致:
设置
.test 1
清理
测试
清理(= 冗余)
. . .
.test N
清理
测试
清理
相反,我想要这个:
(如果在所有测试完成后执行 tearDownX() 方法是可能的)
设置
(测试 1)
清理
测试
. . .
(测试 N)
清理
测试
tearDownX(自我)
清理(最终)
这或多或少是我在过去几年中完成测试设计的方式。 它试图对中断的调试会话(无清理)和脏的初始数据库状态进行防弹。
作为临时解决方案,我在 tearDownClass(cls) 方法中复制了清理方法,但我并不满意。理想情况下,我可以简单地调用 self._cleanup_record 但这是不可能的,因为 tearDownClass 是一个类方法。
我希望这一切都有意义。
谢谢,
亚历山德罗
【问题讨论】:
-
这个用例不会得到很好的支持,因为它被视为一种反模式。您可以编写自己的测试运行程序来执行此操作,但 IMO 您正在自找麻烦。是否有任何原因您不能为每个测试设置和拆卸?
-
我不想在每次测试结束时调用清理,因为根据我的真实世界经验,我必须在每次测试之前(也)清理数据库。因此,在每个测试结果之后进行清理(也),在测试 X 和测试 Y 之间双重调用“清理”(如果我有 10 个测试,它被称为“100% 不必要”的 9 次)。解释说我在每个测试(执行之前)都调用 clenup 仍然使它成为反模式?如果是,您能否解释或链接一些东西,我想更好地了解这一点?谢谢
-
我从来没有遇到过使用 SQLAlchemy 固定装置进行清理的问题。 sqlalchemy-fixtures.readthedocs.io/en/latest
标签: python python-unittest teardown