Модульный тест для скрипта завершения Bash
Я хотел бы написать модульный тест для (довольно сложного) скрипта завершения 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, чтобы проверить значения завершения в тестовом комплекте для моего инструмента?
2 ответа
Скажем, у вас есть скрипт завершения bash в файле с именем 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
Это использует функцию оболочки _asdf
обеспечить завершение для вымышленного asdf
команда. Если мы установим правильные переменные окружения (со страницы руководства bash), то мы сможем получить тот же результат, что и размещение потенциальных расширений в COMPREPLY
переменная. Вот пример этого в unittest:
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
является хорошим для более полного теста.
Решение бонсайкинга почти сработало для меня. Мне пришлось изменить скрипт строки bash. Я добавил дополнительный ';' разделитель исполняемого скрипта bash, иначе выполнение не будет работать в Mac OS X. Не совсем понятно, почему.
Я также немного обобщил инициализацию различных аргументов COMP_ для обработки различных случаев, с которыми я столкнулся.
Окончательное решение - вспомогательный класс для тестирования завершения bash из python, так что приведенный выше тест будет записан в виде:
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