2012-02-04 36 views
10

Tôi muốn viết một bài kiểm tra đơn vị cho một kịch bản hoàn thành Bash (khá phức tạp), tốt hơn với Python - chỉ là một cái gì đó nhận các giá trị của một hoàn thành Bash lập trình. Xét nghiệm này sẽ trông như thế này:Kiểm tra đơn vị cho tập lệnh hoàn thành 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" 

Làm thế nào tôi có thể mô phỏng hoàn Bash lập trình để kiểm tra các giá trị hoàn thành bên trong một TestSuite cho công cụ của tôi?

+2

Liệu [này] (http : //stackoverflow.com/questions/3520936/accesssing-bash-completions-for-specific-commands-programmatically) giúp? Tôi đã không thử nó mặc dù bản thân mình. – Vikas

+1

Nếu bạn muốn mô phỏng tương tác người dùng, 'expect' là bạn của bạn - hãy cài đặt fs/env của bạn trong python và sau đó chạy bash từ bên trong một kịch bản mong đợi với subprocess. Việc thoát có thể phức tạp, nhưng nếu không nó khá đơn giản. – je4d

Trả lời

6

Giả sử bạn có một kịch bản bash hoàn thành trong một tập tin gọi là asdf-completion, bao gồm:

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

này sử dụng hàm vỏ _asdf để cung cấp hoàn cho hư cấu asdf lệnh. Nếu chúng ta thiết lập các biến môi trường thích hợp (từ trang bash man), thì chúng ta có thể nhận được cùng một kết quả, đó là vị trí của các mở rộng tiềm năng vào biến số COMPREPLY. Dưới đây là một ví dụ về làm điều đó trong một 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() 

này nên làm việc cho bất kỳ hoàn sử dụng -F, nhưng có thể làm việc cho người khác là tốt.

nhận xét của je4d để sử dụng expect là cách tốt nhất để kiểm tra hoàn chỉnh hơn.

+0

wow, chính xác những gì tôi muốn. – ifischer

0

giải pháp của bonsaiviking gần như đã hiệu quả đối với tôi. Tôi đã phải thay đổi kịch bản chuỗi bash. Tôi đã thêm một ';' dấu phân tách cho tập lệnh bash được thực thi nếu không việc thực thi sẽ không hoạt động trên Mac OS X. Không thực sự chắc chắn tại sao.

Tôi cũng đã khái quát hóa việc khởi tạo các đối số COMP_ khác nhau một chút để xử lý các trường hợp khác nhau mà tôi đã kết thúc.

Giải pháp cuối cùng là một lớp helper để kiểm tra hoàn thành bash từ python để các kiểm tra trên sẽ được viết như sau:

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

Các lib hoàn nằm dưới https://github.com/lacostej/unity3d-bash-completion/blob/master/lib/completion.py