【问题标题】:Unit Test for Bash completion scriptBash 完成脚本的单元测试
【发布时间】:2012-02-26 13:52:37
【问题描述】:

我想为(相当复杂的)Bash 完成脚本编写单元测试,最好使用 Python - 只是以编程方式获取 Bash 完成值的东西。 测试应如下所示:

def test_completion():
  # trigger_completion should return what a user should get on triggering 
  # Bash completion like this: 'pbt createkvm<TAB>' 
  assert trigger_completion('pbt createkvm') == "module1 module2 module3" 

如何以编程方式模拟 Bash 完成以检查我的工具的测试套件内的完成值?

【问题讨论】:

  • this 有帮助吗?不过我自己没试过。
  • 如果你想模拟用户交互,expect 是你的朋友——在 python 中设置你的 fs/env,然后从带有子进程的期望脚本中运行 bash。转义可能很棘手,但除此之外非常简单。
  • @je4d - 在这种情况下会发生什么?

标签: python bash bash-completion


【解决方案1】:

假设您在名为 asdf-completion 的文件中有一个 bash 完成脚本,其中包含:

_asdf() {
COMPREPLY=()
local cur prev
cur=$(_get_cword)
COMPREPLY=( $( compgen -W "one two three four five six" -- "$cur") )
return 0
}    
complete -F _asdf asdf

这使用 shell 函数 _asdf 为虚构的 asdf 命令提供补全。如果我们设置了正确的环境变量(来自 bash 手册页),那么我们可以获得相同的结果,即将潜在扩展放置到 COMPREPLY 变量中。这是在单元测试中执行此操作的示例:

import subprocess
import unittest

class BashTestCase(unittest.TestCase):
    def test_complete(self):
        completion_file="asdf-completion"
        partial_word="f"
        cmd=["asdf", "other", "arguments", partial_word]
        cmdline = ' '.join(cmd)

        out = subprocess.Popen(['bash', '-i', '-c',
            r'source {compfile}; COMP_LINE="{cmdline}" COMP_WORDS=({cmdline}) COMP_CWORD={cword} COMP_POINT={cmdlen} $(complete -p {cmd} | sed "s/.*-F \\([^ ]*\\) .*/\\1/") && echo ${{COMPREPLY[*]}}'.format(
                compfile=completion_file, cmdline=cmdline, cmdlen=len(cmdline), cmd=cmd[0], cword=cmd.index(partial_word)
                )],
            stdout=subprocess.PIPE)
        stdout, stderr = out.communicate()
        self.assertEqual(stdout, "four five\n")

if (__name__=='__main__'):
    unittest.main()

这应该适用于使用-F 的任何补全,但也可能适用于其他人。

je4d 使用expect 的评论对于更完整的测试来说是一个很好的评论。

【讨论】:

  • 因此,如果我正确阅读了您的 sed(我对此表示怀疑)...您将获取 complete -p {cmd} 的输出并将所有内容剥离到 complete -F,保留名称没有前导空格的功能?因此,如果您的 complete -p {cmd} 输出 complete -F _comp_func somecmd 那么您的 sed 将得到 _comp_func ...我关闭了吗?
  • @Lou 没错。 Python 字符串格式化将参数字符串放入 shell 命令中的环境变量中。该命令本身使用完成函数读取文件,然后以与 Bash 内部相同的方式调用完成函数(如您所描述的那样提取)。最后,它回显出 COMPREPLY 变量,以便subprocess.communicate() 可以在 STDOUT 上读取它。
  • 啊,太好了,感谢您的澄清!如果你没有写过 Seds 可能很难阅读我认为 :)
【解决方案2】:

bonsaiviking 的解决方案几乎对我有用。我不得不更改 bash 字符串脚本。我添加了一个额外的';'分隔符到执行的 bash 脚本,否则在 Mac OS X 上执行将无法正常工作。不太清楚为什么。

我还稍微概括了各种 COMP_ 参数的初始化,以处理我最终遇到的各种情况。

最终的解决方案是一个辅助类来测试从 python 完成的 bash,这样上面的测试就可以写成:

from completion import BashCompletionTest

class AdsfTestCase(BashCompletionTest):
    def test_orig(self):
        self.run_complete("other arguments f", "four five")

    def run_complete(self, command, expected):
        completion_file="adsf-completion"
        program="asdf"
        super(AdsfTestCase, self).run_complete(completion_file, program, command, expected)


if (__name__=='__main__'):
    unittest.main()

补全库位于https://github.com/lacostej/unity3d-bash-completion/blob/master/lib/completion.py下

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2010-11-01
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    相关资源
    最近更新 更多