确保测试用例可以删除它创建的临时目录

Posted

技术标签:

【中文标题】确保测试用例可以删除它创建的临时目录【英文标题】:Ensuring a test case can delete the temporary directory it created 【发布时间】:2012-05-27 06:45:24 【问题描述】:

(平台:Linux,特别是 Fedora 和 Red Hat Enterprise Linux 6)

我有一个用 Python 编写的 integration test,它执行以下操作:

创建一个临时目录 告诉 Web 服务(在 apache 下运行)运行 rsync 作业,将文件复制到该目录中 检查文件是否已正确复制(即配置已正确从客户端传递到通过 Web 服务的 rsync 调用) (尝试)删除临时目录

目前,最后一步失败了,因为 rsync 正在创建文件并将其所有权设置为 apache 用户的所有权,因此测试用例没有删除文件的必要权限。

这个Server Fault question很好地解释了为什么在集成测试设置的情况下清理步骤当前失败。

我目前所做的:我只是不删除测试清理中的临时目录,因此这些集成测试会留下一些虚拟文件,需要手动从/tmp 中清除。

我目前考虑的主要解决方案是添加一个 setuid 脚本专门用于处理测试套件的清理操作。这应该可行,但我希望其他人可以提出更优雅的解决方案。具体来说,如果集成测试客户端不需要关心 apache 进程的 uid,我会非常喜欢它。

我考虑过但因各种原因拒绝的方法:

以 root 身份运行测试用例。这确实有效,但需要以 root 身份运行测试套件相当难看。 在测试套件创建的目录上设置粘性位。据我所知,rsync 忽略了这一点,因为它设置为从远程服务器复制标志。但是,即使将设置调整为仅复制执行位似乎也无济于事,所以我仍然不确定为什么这不起作用。 将测试用户添加到 apache 组。由于 rsync 在没有组写权限的情况下创建文件,这没有帮助。 以测试用户身份运行 Apache 实例并针对该用户进行测试。这有一些优点(因为集成测试不需要 apache 已经在运行),但缺点是我将无法针对已使用生产设置预配置的 Apache 实例运行集成测试确保那些是正确的。因此,即使我最终可能会将此功能添加到测试套件中,但它不会作为更直接地解决当前问题的替代

我真的不想做的另一件事是更改传递给 rsync 的设置,以便测试套件可以正确清理临时目录。这是服务守护进程的集成测试,所以我想使用尽可能接近生产的配置。

【问题讨论】:

您应该只需要对包含目录的父级的写入权限,而不是对单个文件的写入权限。 您能否以与测试相同的用户身份运行 Web 服务,仅用于测试目的?或者,您可以提供其他服务来清理正在使用的目录,但对我来说感觉不太干净。 @James:嗯,好点子。我一直在针对已经运行的 Web 服务器实例运行这些集成测试,因为它的启动时间不是很好,但为了更好地控制文件权限,这样做可能是值得的。 @NiklasB.:当 rsync 将子树复制到临时目录中时,它似乎是以 shutil.rmtree 不喜欢的方式进行的。 @ncoghlan:那么您应该了解更多有关潜在问题的信息。您是否尝试过在控制台中使用 rm -rf 而不是 shutil.rmtree 【参考方案1】:

将测试用户添加到 apache 组(或 httpd 组,以对文件具有组所有权的为准)。

【讨论】:

不幸的是,rsync 正在创建没有组写入权限的文件。不过,我会将其添加到我已经尝试过的事情列表中。【参考方案2】:

借助该服务器故障问题的答案,我能够使用setfacl 找到解决方案。

为集成测试创建临时目录的代码现在执行以下操作(它是 unittest.TestCase 实例的一部分,因此引用了 addCleanup):

local_path = tempfile.mkdtemp().decode("utf-8")
self.addCleanup(shutil.rmtree, local_path)
acl = "d:u:0:rwX".format(os.geteuid())
subprocess.check_call(["setfacl", "-m", acl, local_path])

前两行只是创建临时目录并确保它在测试结束时被删除。

最后两行是新部分,并为目录设置默认 ACL,以便测试用户始终具有读/写访问权限,并且还将对设置了执行位的任何内容具有执行权限。

【讨论】:

为了让一些测试通过 apache 需要读取测试工具创建的文件和目录,我还在临时目录的 ACL 条目中添加了"d:o::rX"

以上是关于确保测试用例可以删除它创建的临时目录的主要内容,如果未能解决你的问题,请参考以下文章

pytest为什么不能运行指定目录下的用例

使 Django 测试用例数据库对 Celery 可见

Spring Boot:如何为删除其余模板编写单元测试用例

pytest中的测试用例执行顺序

JUnit 测试用例中“失败”的实际用途是啥?

(三)接口自动化测试平台之——测试集合接口测试交互页面设计