Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
制作一个从不并行运行的Python单元测试_Python_Unit Testing_Python Unittest - Fatal编程技术网

制作一个从不并行运行的Python单元测试

制作一个从不并行运行的Python单元测试,python,unit-testing,python-unittest,Python,Unit Testing,Python Unittest,tl;dr-我想编写一个Pythonunittest函数,用于删除文件、运行测试并恢复文件。这会导致竞争条件,因为unittest并行运行多个测试,删除和创建一个测试的文件会扰乱同时发生的其他测试 详细的具体示例: 我有一个名为converter.py的Python模块,它在test\u converter.py中有相关的测试。如果在与converter.py相同的目录中有一个名为config\u custom.csv的文件,则将使用自定义配置。如果没有自定义CSV配置文件,则在converte

tl;dr-我想编写一个Python
unittest
函数,用于删除文件、运行测试并恢复文件。这会导致竞争条件,因为
unittest
并行运行多个测试,删除和创建一个测试的文件会扰乱同时发生的其他测试

详细的具体示例:

我有一个名为
converter.py
的Python模块,它在
test\u converter.py
中有相关的测试。如果在与
converter.py
相同的目录中有一个名为
config\u custom.csv
的文件,则将使用自定义配置。如果没有自定义CSV配置文件,则在
converter.py
中内置了默认配置

我使用Python2.7标准库中的
unittest
编写了一个单元测试来验证这种行为。
setUp()
中的单元测试将
config\u custom.csv
重命名为
error\u name.csv
,然后它将运行测试(希望使用默认配置),然后在
tearDown()
中重新命名文件

问题:Python单元测试并行运行,我遇到了糟糕的竞争条件。文件<代码>配置文件自定义.CSV 将以非确定性方式在其他单元测试的中间重命名。在我运行整个测试套件的90%时间里,它至少会导致一个错误或失败

理想的解决方案是告诉
unittest
不要与其他测试并行运行此测试,此测试是特殊的,需要完全隔离


我的解决方法是向搜索配置文件的函数添加一个可选参数。参数仅由测试套件传递。它忽略配置文件而不删除它。实际上删除测试文件更优雅,这正是我真正想要测试的。

首先,大多数支持并行性的测试框架也支持串行某些重要测试的方法。例如,Python支持串行注释(当您使用命令行标志-P作为并行套件启动测试时):


然而,我认为你不应该那样做,我认为你应该停下来,轻视一下。下面是我要说的事情

在这种情况下,测试基本上已经确定了代码的一个条件,因此需要为您突出一点内聚性

你现在应该做的是意识到“converter.py”有太多的责任,它不仅要在幕后执行一些复杂的操作,而且还要负责管理自己的创建和设置,这对它来说可能是太多了


如果您有一个对象可以管理该文件中的读取,那么您就可以轻松地对其进行模拟/存根,并生成您所描述的要测试的条件。

问题在于
config\u custom.csv
的名称本身应该是一个可配置参数。然后,每个测试只需查找
config\u custom\u.csv
,任何数量的测试都可以并行运行


清理整个套件只需清除
config\u custom.*.csv
,因为此时我们不需要它们中的任何一个。

最好的测试策略是确保对不相交的数据集进行测试。这将绕过任何竞争条件,使代码更简单。如果您使用上下文管理器,我也会模拟
打开
进入
/
退出
。这将允许您伪造文件不存在的事件。

我经常需要在完全隔离的情况下运行测试。我发现,唯一能保持一致的方法是将这些测试放在不同的类中。同意在测试中处理配置文件仍然是一种痛苦


对于我现在正在做的事情,我也可以尝试以更确定的方式运行测试

文件名实际上是可配置的。如果没有发现任何东西,我真的想测试一下行为。我在最初的问题中提到的我的工作与这个建议基本相似,它实际上并没有测试我想要的行为。我的解决方法是告诉配置文件查找器“不要查找任何配置文件”。您的建议基本上是“只查找特定的配置文件”。我想测试它的行为,如果它看起来正常,但什么也没有发现。我不想关闭或限制搜索本身。@SerMetAla使用不同的文件是一种不引入锁定的好方法。如果你不能使用不同的文件集,那么你应该使用锁。我知道Fabric,但我不知道
@serial
装饰器,所以谢谢你。关于单一责任原则:我觉得我已经很好地坚持了
converter.py
只是一个文件,但它有多个功能(不是太多)。其中一个函数是
load\u config()
,它只有一个职责。如果它找到一个配置文件,它将加载它,否则它将使用默认值。它实际上不需要任何参数,但我添加了
load\u config(use\u defaults=False)
并仅在单元测试期间传入
True
,这就是您建议的。这是次优的。(第2部分,共2部分)使用这样的kwarg有两个问题:首先,
converter.py
的源代码变得更加复杂。我刚刚在converter.py中添加了一个任何人都不应该使用的特性,只有单元测试应该使用它。这是属于测试的东西的定义,而不是代码本身。第二:如果所有的测试都通过了,但实际上找不到一个文件会导致硬崩溃怎么办?单元测试再也看不到这个问题了。单元测试将通过。如果
os.listdir()
发生了变化,并且出现了回归,我不会看到它。是的,我同意你的观点
from fabric.api import *

def runs_in_parallel():
    pass

@serial
def runs_serially():
    pass