在 Elixir 中断言 zip 存档内容的最佳方法是什么?
What is the best way to assert the contents of a zip archive in Elixir?
目前我在做什么:
- 通过压缩 file/directory 来测试函数。断言它存在。
- 使用
: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}]}
Erlang 的 :zip
模块并不是很容易使用,我会尝试为您分解它。
首先,我们需要 zip_file
记录的适当表示,以便 Erlang 能够正确使用它。否则,我们将不得不用 lot 元素对元组进行匹配,这只会不必要地使我们的代码混乱。以下模块主要基于 the File.Stat
implementation from Elixir 并且允许我们使用简单的点符号访问那些笨重的元组中的值。
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
模块构建一个小型包装器 class。它不会包装所有方法,只是包装我们将在此处使用的方法。我还添加了一个 list_files/1
函数,它只包含 returns 个文件,不包括列表中的目录和注释。
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 存档上留下进一步的操作和断言供您实施,希望这能帮助您入门。
您表示要验证 zip 文件及其内容。虽然这部分是一个 Elixir/Erlang 问题,但它也超出了这个简单的上下文。这是我的建议:
创建所有文件的列表并为每个文件创建校验和
文件。将其保存在某处。
压缩整个文件。
将文件从 zip 解压缩到不同的目录。
统计解压目录下的文件--如果文件个数
不一样,测试失败。
对照步骤 1 中创建的列表检查提取的文件列表。如果文件列表不匹配,则测试失败。
计算所有文件的校验和。比较校验和
针对步骤 1 中存储的校验和。如果它们不匹配,则测试
失败。
综上所述,这让我觉得这是一个毫无意义的练习,因为基本上您要测试的是 Erlang zip 库。如果 Erlang zip 库中存在缺陷,人们早就会大声抱怨,您只需通过谷歌搜索就可以找出缺陷。
也就是说,虽然您可以为此编写单元测试,但我觉得这是在浪费时间。
目前我在做什么:
- 通过压缩 file/directory 来测试函数。断言它存在。
- 使用
: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}]}
Erlang 的 :zip
模块并不是很容易使用,我会尝试为您分解它。
首先,我们需要 zip_file
记录的适当表示,以便 Erlang 能够正确使用它。否则,我们将不得不用 lot 元素对元组进行匹配,这只会不必要地使我们的代码混乱。以下模块主要基于 the File.Stat
implementation from Elixir 并且允许我们使用简单的点符号访问那些笨重的元组中的值。
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
模块构建一个小型包装器 class。它不会包装所有方法,只是包装我们将在此处使用的方法。我还添加了一个 list_files/1
函数,它只包含 returns 个文件,不包括列表中的目录和注释。
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 存档上留下进一步的操作和断言供您实施,希望这能帮助您入门。
您表示要验证 zip 文件及其内容。虽然这部分是一个 Elixir/Erlang 问题,但它也超出了这个简单的上下文。这是我的建议:
创建所有文件的列表并为每个文件创建校验和 文件。将其保存在某处。
压缩整个文件。
将文件从 zip 解压缩到不同的目录。
统计解压目录下的文件--如果文件个数 不一样,测试失败。
对照步骤 1 中创建的列表检查提取的文件列表。如果文件列表不匹配,则测试失败。
计算所有文件的校验和。比较校验和 针对步骤 1 中存储的校验和。如果它们不匹配,则测试 失败。
综上所述,这让我觉得这是一个毫无意义的练习,因为基本上您要测试的是 Erlang zip 库。如果 Erlang zip 库中存在缺陷,人们早就会大声抱怨,您只需通过谷歌搜索就可以找出缺陷。
也就是说,虽然您可以为此编写单元测试,但我觉得这是在浪费时间。