如何对比两个嵌套数据结构以进行单元测试?
对于那些了解perl的人,我在找一个类似于Test::Deep::is_deeply()
的东西在Python中。
在Python的unittest中,我可以方便地比较嵌套的数据结构,如果我期望它们是相等的:
self.assertEqual(os.walk('some_path'),
my.walk('some_path'),
"compare os.walk with my own implementation")
不过,在我想要的测试中,os.walk
元组中各个子列表的文件顺序并不重要。
如果只是这个单一的测试,写个简单的解决方案也没问题。但我想象中会有多个测试,涉及到不同结构的嵌套数据。我希望能有一个通用的解决方案。
我查看了Python自己的unittest文档,还看了pyUnit和nose及其插件。活跃的维护也是使用时一个重要的考虑因素。
我最终的目标是希望有一组描述性类型,比如UnorderedIterable
、SubsetOf
、SupersetOf
等,可以用来描述一个嵌套的数据结构,然后利用这个描述来比较两个实际的数据集。
在os.walk的例子中,我想要的类似于:
comparison = OrderedIterable(
OrderedIterable(
str,
UnorderedIterable(),
UnorderedIterable()
)
)
上面的内容描述了list(os.walk())
会返回的数据结构。为了在单元测试中比较数据A
和数据B
,当前的路径名称会被转换成str()
,然后目录和文件列表会被比较,忽略顺序,使用:
self.assertDeep(A, B, comparison, msg)
有没有这样的东西呢?还是说这是一项微不足道的任务,以至于人们自己写?我觉得自己能做到,但我不想重新发明轮子,尤其是不想编写完整的正交类型集合、测试等等。简而言之,我不会发布它,这样下一个人又得重新写一遍……
2 个回答
这不是一个解决方案,而是目前为了解决问题中提到的特定例子而采用的临时办法:
os_walk = list(os.walk('some_path'))
dt_walk = list(my.walk('some_path'))
self.assertEqual(len(dt_walk), len(os_walk), "walk() same length")
for ((osw, osw_dirs, osw_files), (dt, dt_dirs, dt_files)) in zip(os_walk, dt_walk):
self.assertEqual(dt, osw, "walk() currentdir")
self.assertSameElements(dt_dirs, osw_dirs, "walk() dirlist")
self.assertSameElements(dt_files, osw_files, "walk() fileList")
从这个例子中,我们可以看到代码量其实挺多的。同时,我们也能发现,Python的unittest工具已经具备了大部分所需的功能。
Python Deep 这个项目看起来是为了重新实现 perl 语言中的 Test::Deep。这个项目的作者正是 Test::Deep 的原作者。最后一次更新是在2016年初。
更新(2018年8月):最新的版本(2016年2月)可以在 PyPi/Deep 找到。