我想为一个(相当复杂的)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完成以检查我的工具的测试套件内的完成值?
答案 0 :(得分:6)
假设您在名为asdf-completion
的文件中有bash-completion脚本,其中包含:
_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
的评论对于更完整的测试来说是一个很好的评论。
答案 1 :(得分:0)
我还稍微概括了各种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
下