2012-02-04 9 views
10

Me gustaría escribir un Test Unit para un guión de terminación Bash (bastante complejo), preferiblemente con Python, algo que obtiene los valores de una finalización Bash programáticamente. La prueba debe tener este aspecto:Prueba unitaria para el guión de finalización de 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" 

¿Cómo puedo simular la terminación Bash mediante programación para comprobar los valores de terminación dentro de un banco de pruebas para mi herramienta?

+2

las hace [esto] (http : //stackoverflow.com/questions/3520936/accesssing-bash-completions-for-specific-commands-programmatically) ayuda? Aunque no lo he intentado solo. – Vikas

+1

Si desea simular la interacción del usuario, 'expect' es su amigo: realice su configuración de fs/env en python y luego ejecute bash desde dentro de un script de espera con subproceso. El escape puede ser complicado, pero por lo demás es bastante sencillo. – je4d

Respuesta

6

Digamos que tiene un script bash-completado en un archivo llamado asdf-completion, que contiene:

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

Este utiliza la función Shell _asdf para proporcionar terminaciones para el comando de ficción asdf. Si establecemos las variables de entorno correctas (desde la página man de bash), podemos obtener el mismo resultado, que es la ubicación de las posibles expansiones en la variable COMPREPLY. He aquí un ejemplo de hacer que en un 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() 

Esto debería funcionar para cualquier terminaciones que utilizan -F, pero puede funcionar para otros también.

comentario de je4d para usar expect es uno bueno para una prueba más completa.

+0

guau, exactamente lo que quería. – ifischer

0

La solución de bonsaiviking casi funcionó para mí. Tuve que cambiar el script de cadena de bash. Agregué un extra ';' separador del script bash ejecutado; de lo contrario, la ejecución no funcionaría en Mac OS X. No estoy seguro de por qué.

También generalicé un poco la inicialización de varios argumentos COMP_ para manejar los diversos casos con los que terminé.

La solución final es una clase de ayuda para poner a prueba la finalización fiesta del pitón de manera que la prueba anterior se escribiría:

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

El lib finalización está situado debajo https://github.com/lacostej/unity3d-bash-completion/blob/master/lib/completion.py