可复现性测试框架

3
我正在寻找一个支持长时间、费力的正确性测试的测试或集成框架。只有在影响测试的代码发生变化时,才应该重新运行测试。
理想情况下,测试框架应该:
- 找到测试代码的位置 - 生成它的哈希值 - 运行代码并将结果写入以哈希值命名的输出文件中 - 如果已经存在,则跳过 - 提供简单的概述,说明哪些测试成功了,哪些失败了
如果测试必须指定其所依赖的模块和文件,则也可以接受。
Python 是最理想的选择,但这个问题可能高级到其他语言也适用。
也许已经存在一个测试或构建集成框架,我可以将其调整以符合这种行为?

你看过nose了吗?它很受欢迎,用于测试。 - Wingzero
可能与 https://softwarerecs.stackexchange.com/ 相关。 - dsgriffin
2个回答

1

基本上,您需要跟踪测试的执行情况,以便检查它是否发生了变化。

Python 代码可以使用 sys.settrace(tracefunc) 进行跟踪。有一个模块 trace 可以帮助实现跟踪。

但是,如果不仅仅是 Python 代码 - 如果测试还执行其他程序、测试输入文件等,并且您也需要监视其更改,则需要在操作系统级别进行跟踪,例如 stracedtracedtruss

我创建了一个简单的测试框架的演示/原型,仅运行与上次运行时有变化的测试:https://gist.github.com/messa/3825eba3ad3975840400 它使用了 trace 模块。它的工作方式如下:

  1. 收集测试,每个测试都有一个名称标识
  2. 从JSON文件中加载测试指纹(如果存在)
  3. 对于每个测试:
    • 如果指纹与指纹列表中列出的函数的当前字节码匹配,则跳过该测试
    • 否则运行测试
      1. 在运行时跟踪它,记录所有被调用的函数
      2. 创建包含函数名称和每个记录的函数的字节码MD5散列值的测试指纹
  4. 将更新后的测试指纹保存到JSON文件中

但是有一个问题:它很。使用trace.Trace跟踪代码运行速度比不跟踪慢大约40倍。因此,也许您最好直接运行所有测试而不进行跟踪 :) 但如果跟踪器像覆盖率模块中的C一样实现,它应该会更快。 (Python的trace模块不是C语言编写的。)

也许其他技巧可以提高速度。也许你只对一些顶级函数是否更改感兴趣,所以不需要跟踪所有函数调用。
你考虑过其他加速昂贵测试的方法吗?比如并行化、ramdisk(tmpfs)…例如,如果你针对数据库进行测试,请不要使用“系统”或开发环境,而是从tmpfs运行具有轻量级配置(无预分配、无日志…)的特殊数据库实例。当然,如果可能的话 - 有些测试需要在类似于生产环境的配置下运行。
一些测试框架(或其插件)可以仅运行上次失败的测试 - 这是不同的,但有点类似的功能。

也许另一个选项是从Python文件的哈希值创建指纹(即不执行它)?在这种情况下,例如fib.py的md5哈希值。 - j13r
@j13r 是的,但是你需要以某种方式知道给定的测试使用了给定的.py文件。这就是为什么我使用了跟踪,但如果有其他方法比跟踪更好的话那就更好了。 - Messa
当然,你可以对包含测试函数的文件进行哈希处理,但我认为你也想要对所有被该测试执行的其他文件进行哈希处理。 - Messa
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Messa
我有一个想法 - 或许不需要追踪函数执行以获取它执行的其他函数列表;也许我可以通过检查函数字节码来获取该列表... "静态分析" :) - Messa
显示剩余3条评论

0

这可能不是最有效的方法,但可以使用Python的pickle模块完成此操作。

import pickle

在文件末尾,将其保存为 pickle。
myfile = open('myfile.py', 'r') #Your script
savefile = open('savefile.pkl', 'w') #File the script will be saved to
#Any file extension can be used but I like .pkl for "pickle"
mytext = myfile.readlines()
pickle.dump(mytext, savefile) #Saves list from readlines() as a pickle
myfile.close()
savefile.close()

然后在你的脚本开头(在你已经将其pickle一次之后),添加检查它与pickle相匹配的代码片段。

myfile = ('myfile.py', 'r')
savefile = ('savefile.pkl', 'r')
mytext = myfile.readlines
savetext = pickle.load(savefile)
myfile.close()
savefile.close()

if mytext == savetext:
    #Do whatever you want it to do
else:
    #more code

应该可以。虽然有点长,但是它是纯Python的,应该能做到你想要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接