unit test bash 删除超过一定天数的文件的脚本函数
unit test bash script function which deletes files older than certain number of days
我在 bash/shell 脚本编写方面经验不多,最近才开始使用 Bats 框架或库编写一些带有单元测试的 bash 脚本。目前正在编写一个脚本,需要删除超过一定天数的文件。下面是函数。
function deleteFilesOlderThan() {
echo "Deleting files older than days"
eval "find ./test-files -mtime + -exec rm {} \;"
}
是否可以对上述功能进行单元测试,因为它有复杂的命令?如果不可能,我们可以用其他方式重写上面的函数,以便它可以进行单元测试。请指教
在我看来,您问的是三个不同的问题:
- 我的代码好用吗?
- 如何为 BASH
编写一般测试
- 如何测试此特定代码?
因为这听起来更像是代码审查请求,它可能更适合 https://codereview.stackexchange.com/ 但我还是会在这里回答...
这个命令并没有那么复杂。但即使是,您也会测试代码的 side-effect,而不是代码本身。所以代码的复杂性甚至并不重要...
无论如何,测试应该是这样的:
@test "deleteFilesOlderThan deletes files" {
# Arrange
touch -t 123412312345 ./test-files/test.txt
# Act
deleteFilesOlderThan 1000
# Assert
[ ! -f ./test-files/test.txt ]
}
您可以添加更多测试,例如使用 assert_output
检查输出,并检查 较新的 文件不被删除。
代码可以在不重写的情况下进行测试,但代码中存在一些潜在问题:
正如评论中所述,eval
并不是真正需要的。 find
命令可以 运行 正常 as-is,无需包裹在 eval
.
中
有没有检查。 None。完全没有。您可能需要 至少 检查是否确实提供了 </code>。你<em>也可以</em>检查它是否是一个整数。</p>
</li>
<li><p>您可以检查 <code>test-files
是否确实存在
test-files
目录是hard-coded。我会把它作为函数的参数。这样就可以为测试提供与真实路径不同的路径。
这些变化看起来像这样:
function deleteFilesOlderThan() {
local days="${1:?Two parameters required: <days> <path>}"
local path="${2:?Two parameters required: <days> <path>}"
if [[ -n ${days} && ${days} = *[!0123456789]* ]]; then
echo "ERROR: Given days '${days}' is not an integer" >&2
elif [[ ! -d "${path}" ]]; then
echo "ERROR: Given path '${path}' is not a directory" >&2
else
echo "Deleting files older than days in ${path}"
find "${path}" -mtime "+" -exec rm {} \;
fi
}
当然,现在代码多了,测试也应该多了。我将把它留作 reader.
的练习
如果您还不熟悉它,您可能想看看 shellcheck。如果您编写任何可能导致问题的代码,它会警告您。
您可能还想查看 shfmt
(来自 mvdan.cc/sh 包)以格式化 shell 脚本。
我在 bash/shell 脚本编写方面经验不多,最近才开始使用 Bats 框架或库编写一些带有单元测试的 bash 脚本。目前正在编写一个脚本,需要删除超过一定天数的文件。下面是函数。
function deleteFilesOlderThan() {
echo "Deleting files older than days"
eval "find ./test-files -mtime + -exec rm {} \;"
}
是否可以对上述功能进行单元测试,因为它有复杂的命令?如果不可能,我们可以用其他方式重写上面的函数,以便它可以进行单元测试。请指教
在我看来,您问的是三个不同的问题:
- 我的代码好用吗?
- 如何为 BASH 编写一般测试
- 如何测试此特定代码?
因为这听起来更像是代码审查请求,它可能更适合 https://codereview.stackexchange.com/ 但我还是会在这里回答...
这个命令并没有那么复杂。但即使是,您也会测试代码的 side-effect,而不是代码本身。所以代码的复杂性甚至并不重要...
无论如何,测试应该是这样的:
@test "deleteFilesOlderThan deletes files" {
# Arrange
touch -t 123412312345 ./test-files/test.txt
# Act
deleteFilesOlderThan 1000
# Assert
[ ! -f ./test-files/test.txt ]
}
您可以添加更多测试,例如使用 assert_output
检查输出,并检查 较新的 文件不被删除。
代码可以在不重写的情况下进行测试,但代码中存在一些潜在问题:
正如评论中所述,
中eval
并不是真正需要的。find
命令可以 运行 正常 as-is,无需包裹在eval
.有没有检查。 None。完全没有。您可能需要 至少 检查是否确实提供了
</code>。你<em>也可以</em>检查它是否是一个整数。</p> </li> <li><p>您可以检查 <code>test-files
是否确实存在test-files
目录是hard-coded。我会把它作为函数的参数。这样就可以为测试提供与真实路径不同的路径。
这些变化看起来像这样:
function deleteFilesOlderThan() {
local days="${1:?Two parameters required: <days> <path>}"
local path="${2:?Two parameters required: <days> <path>}"
if [[ -n ${days} && ${days} = *[!0123456789]* ]]; then
echo "ERROR: Given days '${days}' is not an integer" >&2
elif [[ ! -d "${path}" ]]; then
echo "ERROR: Given path '${path}' is not a directory" >&2
else
echo "Deleting files older than days in ${path}"
find "${path}" -mtime "+" -exec rm {} \;
fi
}
当然,现在代码多了,测试也应该多了。我将把它留作 reader.
的练习如果您还不熟悉它,您可能想看看 shellcheck。如果您编写任何可能导致问题的代码,它会警告您。
您可能还想查看 shfmt
(来自 mvdan.cc/sh 包)以格式化 shell 脚本。