2012-02-04 2 views
10

Я хотел бы написать Unit Test для (довольно сложного) сценария завершения Bash, предпочтительно с Python - это просто то, что программным путем получает значения Bash. Тест должен выглядеть следующим образом:Идентификатор модуля для сценария завершения 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" 

Как я могу имитировать Баш завершения программно проверить значение завершения внутри TestSuite для моего инструмента?

+2

Does [это] (HTTP : //stackoverflow.com/questions/3520936/accesssing-bash-completions-for-specific-commands-programmatically) помогает? Я сам не пробовал. – Vikas

+1

Если вы хотите имитировать взаимодействие пользователя, 'expect' - ваш друг - выполните настройку fs/env в python, а затем запустите bash из сценария ожидания с подпроцессом. Ускорение может быть сложным, но в остальном это довольно просто. – je4d

ответ

6

Скажет, у вас есть скрипт, Баш-завершение в файле 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 является хорошим для более полного теста.

+0

Вау, именно то, что я хотел. – ifischer

0

Решение bonsaiviking почти сработало для меня. Мне пришлось изменить строковый скрипт bash. Я добавил дополнительный ';' разделитель к исполняемому сценарию bash, иначе выполнение не будет работать в Mac OS X. Не совсем понятно, почему.

Я также обобщил инициализацию различных аргументов COMP_ немного, чтобы обрабатывать различные случаи, в которых я закончил.

Окончательное решение является вспомогательным классом, чтобы проверить завершение Баш из питона так, что вышеописанное испытание было бы записать в виде:

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() 

Завершение Lib расположен под https://github.com/lacostej/unity3d-bash-completion/blob/master/lib/completion.py

Смежные вопросы