在Elixir中,断言zip归档文件的内容最佳方法是什么?

5

目前我正在做的事情:

  1. 通过让它压缩文件/目录来测试功能。断言它存在。
  2. 使用 :zip.t:zip.tt 让它列出 zip 文件夹的内容,以查看是否符合预期。

不知怎么回事,我觉得我漏了什么。使用 :zip.table 进行测试是否更好?这个功能看起来很混乱。有人能提供如何使用它的示例吗?下面是我得到的输出示例,但我无法想出如何将其转化为测试?md5sum 是否是 zip 存档的更好测试方法?

iex(4)> :zip.table('testing.zip')
{:ok,
 [{:zip_comment, []},
  {:zip_file, 'mix.exs',
   {:file_info, 930, :regular, :read_write, {{2015, 7, 15}, {2, 11, 9}},
    {{2015, 7, 15}, {2, 11, 9}}, {{2015, 7, 15}, {2, 11, 9}}, 54, 1, 0, 0, 0, 0,
    0}, [], 0, 444},
  {:zip_file, 'mix.lock',
   {:file_info, 332, :regular, :read_write, {{2015, 7, 15}, {2, 9, 6}},
    {{2015, 7, 15}, {2, 9, 6}}, {{2015, 7, 15}, {2, 9, 6}}, 54, 1, 0, 0, 0, 0,
    0}, [], 481, 152}]}

1
在谷歌搜索“erlang zip”时,第一个结果显示Erlang的zip模块。当您在这里提问时,请至少表现出一些努力。尝试自己开始解决问题,然后遇到问题时再回来提出具体问题。 - Patrick Oscity
抱歉之前表述不够清晰,没有表达出我真正想要的。我已经澄清了问题。 - Muhammad Lukman Low
1
那么你想编写一个测试来断言 zip 文件的内容吗?你只想断言文件名还是也包括压缩文件的内容? - Patrick Oscity
最好是包括压缩文件中的所有文件/文件夹及其完整性。 - Muhammad Lukman Low
我在下面添加了一个答案,简而言之,我认为围绕压缩和解压文件构建单元测试基本上是浪费时间。你基本上是在测试Erlang zip库。 - Onorio Catenacci
2个回答

8

来自 Erlang 的 :zip 模块不是很容易使用,我将尝试为您分解其内容。

首先,我们需要适当的表示 zip_file 记录,以便从 Erlang 中能够正确地使用它。否则,我们将不得不对具有大量元素的元组进行匹配,这只会使我们的代码变得混乱不堪。以下模块在很大程度上基于 Elixir 中的 File.Stat 实现,并将允许我们通过简单的点符号标记访问那些笨重元组中的值。

require Record

defmodule Zip.File do
  record = Record.extract(:zip_file, from_lib: "stdlib/include/zip.hrl")
  keys   = :lists.map(&elem(&1, 0), record)
  vals   = :lists.map(&{&1, [], nil}, keys)
  pairs  = :lists.zip(keys, vals)

  defstruct keys

  def to_record(%Zip.File{unquote_splicing(pairs)}) do
    {:zip_file, unquote_splicing(vals)}
  end

  def from_record(zip_file)
  def from_record({:zip_file, unquote_splicing(vals)}) do
    %Zip.File{unquote_splicing(pairs)}
    |> Map.update!(:info, fn(info) -> File.Stat.from_record(info) end)
  end
end

我们现在可以在Erlang的zip模块周围构建一个小包装类。它并没有包装所有的方法,只是我们将在这里使用的方法。我还添加了一个`list_files/1`函数,仅返回文件列表中排除目录和注释。
defmodule Zip do
  def open(archive) do
    {:ok, zip_handle} = :zip.zip_open(archive)
    zip_handle
  end

  def close(zip_handle) do
    :zip.zip_close(zip_handle)
  end

  def list_dir(zip_handle) do
    {:ok, result} = :zip.zip_list_dir(zip_handle)
    result
  end

  def list_files(zip_handle) do
    list_dir(zip_handle)
    |> Enum.drop(1)
    |> Enum.map(&Zip.File.from_record/1)
    |> Enum.filter(&(&1.info.type == :regular))
  end
end

假设我们有以下zip归档文件用于测试:
cd /tmp
touch foo bar baz
zip archive.zip foo bar baz

现在,您可以断言zip归档文件中的文件名:

test "files are in zip" do
  zip = Zip.open('/tmp/archive.zip')
  files = Zip.list_files(zip) |> Enum.map(&(&1.name))
  Zip.close(zip)
  assert files == ['foo', 'bar', 'baz']
end

我会留下进一步的操作和断言关于zip档案供您实现,并希望这能帮助您入门。


0

您表示想要验证zip文件及其内容。虽然这部分是Elixir/Erlang问题,但它也有一定的超出简单上下文的范围。以下是我的建议:

  1. 创建所有文件的列表,并为每个文件创建校验和。将其保存在某个地方。

  2. 压缩整个文件夹。

  3. 将文件从zip中提取到另一个目录中。

  4. 计算提取目录中的文件数-如果文件数不同,则测试失败。

  5. 检查从步骤1中创建的列表中提取的文件列表。如果文件列表不匹配,则测试失败。

  6. 计算所有文件的校验和。将校验和与步骤1中存储的校验和进行比较。如果不匹配,则测试失败。

尽管如此,我认为这是一个相当无意义的练习,因为基本上您正在测试的是Erlang zip库。如果Erlang zip库存在缺陷,人们已经会大声抱怨了,您只需通过Google搜索即可找到缺陷。

也就是说,虽然你可以为此编写单元测试,但我觉得这是浪费时间。


如果您编写一个包装函数来增加自己的功能,那么在zip周围编写它是否仍然有用呢? - Muhammad Lukman Low
如果您编写了一个包装器,那么为包装器功能编写单元测试是有意义的。但是,听起来您没有包装任何内容。 - Onorio Catenacci

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