Bash完成脚本的单元测试

Ing*_*her 10 python bash bash-completion

我想为一个(相当复杂的)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" 
Run Code Online (Sandbox Code Playgroud)

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

bon*_*ing 6

假设您在名为的文件中有bash-completion脚本asdf-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
Run Code Online (Sandbox Code Playgroud)

这使用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()
Run Code Online (Sandbox Code Playgroud)

这适用于任何使用的完成-F,但也可能适用于其他完成.

expect对于更完整的测试,je4d的使用评论是一个很好的评论.