我需要验证python应用程序生成的zip文件的内容。我希望每次运行应用程序时,它都会生成具有相同内容的完全相同的zip文件(当给出相同的输入时)。根据内容,我的意思是仅压缩文件的内容,而不是这些文件的元信息或zip文件。
问题是zip文件会保留一些元信息,例如每个文件的创建时间,每次运行应用程序时都会有所不同。遗憾的是,这些zip文件可能包含数百万个小文件,这使得提取和计算每个小文件的哈希值非常不愉快。
进行此类测试的好方法是什么?我一直在尝试hashlib的“md5”方法,即将zip文件的md5值与先前计算的值进行比较。但是,每次运行应用程序时md5值都不同,因为元信息不同。不知道怎样才能做这个测试?如果可能的话,我不介意使用相同的元信息提取和重新压缩它。请注意,zip文件包含多层目录。
答案 0 :(得分:1)
根据我的理解,您正在尝试编写自动化测试,以验证您的zip文件的内容是否符合预期。
md5似乎是一个很好的候选人。现在,如果您在zip文件中有时间相关数据,我建议您使用https://github.com/spulec/freezegun。它的目的是"暂停"时间,以便所有对datetime
函数(now()
,today()
...)的调用都将返回已知值。你可以这样做:
from freezegun import freeze_time
def test_zipping():
with freeze_time("2012-01-14 12:34:56"):
zipfile = create_zip_file(data)
md5 = hashlib.md5()
with open(zipfile_name) , "rb" ) as f:
data = f.read(block_size)
if not data:
break
md5.update(data)
assert md5.digest() == expected_md5_value
有了这个,您应该能够从测试中取出与时间相关的随机性。
(受Get MD5 hash of big files in Python的启发,因为你的zip文件看起来很大)
答案 1 :(得分:1)
我喜欢Laurent S的基本想法,以确保在运行测试时具有相同的条件。只要您不考虑安全问题我同意使用md5。
由于你对每次运行中不同的元数据非常不确定,我很好奇并做了一个简短的测试。
zip t1 t00*png
zip t2 t00*png
现在进行一些改变:
touch t00*.png
zip t3 t00*png
结果:
md5sum *.zip
760a4a1c52f3bc6cdd29c1fff7b94c1f t1.zip
760a4a1c52f3bc6cdd29c1fff7b94c1f t2.zip
83a8dcb9fe0d50e7b2b8012c8842005e t3.zip
这意味着 - 只要没有更改元数据,我的zip [1]版本最终会产生可重复的内容。
根据定义,您的更改不属于文件内容(例如,JPEG&#EXIF数据也是元数据,是文件的一部分 - 而文件访问日期不是)。否则你根本就没有机会使用任何哈希函数。
因此,如果你想要一个类似的结果,而文件内容是相同的,但他们的元数据(文件系统的元数据)不是你只需调整就可以节省大量的精力元数据。
当你在这里进行某种单元测试时,你甚至可以使用它来验证md5-sum与相同的与调整的元数据和不同的没有。
概念证明:
touch t00*.png -d '2000-01-01T0:00'
zip t1 t00*png
touch t00*.png -d
zip t2 t00*png
touch t00*.png -d '2000-01-01T0:00'
zip t3 t00*png
结果:
md5sum *.zip
a1e713c1d91a0042b37043c83bb98d1b t1.zip
3085aa53bee69df4be783636b87ed62c t2.zip
a1e713c1d91a0042b37043c83bb98d1b t3.zip
最后但并非最不重要的是,您可以尝试调整与您的测试无关的ZIP文件区域。由于ZIP似乎是一个表现良好的容器格式,我的更改的元数据显示在整齐的距离 - 加强了我的假设,即它们是每个文件的页眉/页脚:
cat t1.zip| xxd -ps -c 20 > t1.hd
cat t2.zip| xxd -ps -c 20 > t2.hd
diff t1.hd t2.hd
1c1
< 504b03041400000008000000212822aad7cacc0b
---
> 504b0304140000000800c37a574a22aad7cacc0b
3c3
< 09000370356d3870356d3875780b000104e80300
---
> 0900030df0ae580df0ae5875780b000104e80300
3432c3432
< 6082504b030414000000080000002128143698a4
---
> 6082504b0304140000000800c37a574a143698a4
3434c3434
< 555409000370356d3870356d3875780b000104e8
---
> 55540900030df0ae580df0ae5875780b000104e8
19691,19693c19691,19693
...
请注意元数据更改导致的明显差异。
[1] Linux 4.9.9-1-ARCH #1 SMP PREEMPT Thu Feb 9 19:07:09 CET 2017 x86_64 GNU/Linux, <br>
Zip 3.0 (July 5th 2008), by Info-ZIP, Compiled with gcc 5.3.0 for Unix (Linux ELF) on Jan 12 2016.