2014-02-14 41 views
3

tl; dr -我想编写一个Python unittest函数,该函数删除文件,运行测试并恢复文件。这会导致竞争条件,因为unittest并行运行多个测试,并且为一个测试删除和创建文件会混淆同时发生的其他测试。做一个从未平行运行的Python单元测试

长具体的例子:

我有一个Python模块命名converter.py并已在test_converter.py相关测试。如果在与converter.py相同的目录中存在名为config_custom.csv的文件,则将使用自定义配置。如果没有自定义的CSV配置文件,那么内置converter.py的默认配置。

我使用Python 2.7标准库中的unittest编写了一个单元测试来验证此行为。 setUp()中的单元测试会将config_custom.csv重命名为wrong_name.csv,然后它将运行测试(希望使用默认配置),然后在tearDown()中将文件重命名为应该的方式。

问题: Python单元测试并行运行,我得到了糟糕的竞争条件。文件config_custom.csv将以非确定性方式在其他单元测试中间重命名。在我运行整个测试套件的90%时间内,至少会导致一个错误或失败。

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

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

回答

1

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

from fabric.api import * 

def runs_in_parallel(): 
    pass 

@serial 
def runs_serially(): 
    pass 

不过,我不认为你应该做的,我觉得你应该停下来蔑视一下。在Single Responsibility Principal之后,这就是我所说的。

您处于一种测试基本上确定了您的代码状况的情况,它突出显示了您的凝聚力点。

你现在应该做的事情是认识到“converter.py”的责任过多,它不仅执行一些复杂的操作,而且还负责管理它自己的创建和设置,可能太多了。

也许如果你有一个可以管理读取该文件的对象,那么你可以很容易地模拟/存根并产生你正在描述的你想测试的条件。

1

问题是config_custom.csv的名称本身应该是一个可配置的参数。然后每个测试可以简单地寻找config_custom_<nonce>.csv,并且任何数量的测试可以并行运行。

清理整个套件可以清除config_custom_*.csv,因为我们在这一点上不需要其中的任何一个。

0

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