En el ciclo de desarrollo: escribir un test que falla, modificar el código para que el test pase e iterar, hay tareas que se repiten, como lanzar los test después de hacer modificaciones.
Llamar a los tests implica usar un comando como
python -m unittest tests
O desde un setup.py
python setup.py test
En cualquiera de los dos casos anteriores es necesario pasar del editor a otra consola y ejecutar un comando cada vez que se realiza una modificación.
Para facilitar el proceso descrito es preferible usar alguna herramienta que vigile los archivos modificados, y cuando corresponda, lance tareas establecidas.
A continuación se presenta grunt, una solución para el problema propuesto.
Instalando Grunt
Para instalar grunt globalmente (en todo el sistema) es necesario tener nodejs y su package manager npm. En mi caso fue fácil instalar nodejs, ya que estaba trabajado en una box de nitrous.io, bastó con parts install nodejs
.
Con npm, instalar grunt-cli
npm install -g grunt-cli
Crear un archivo package.json
con nombre de proyecto y versión, en el cual se registraran las dependencias
// package.json
{
"name": "pythontest",
"version": "0.0.1"
}
E instalar lo necesario para grunt en el proyecto
npm install grunt grunt-contrib-watch --save-dev
La opción --save-dev
se encargará de registrar las dependencias en el archivo package.json
.
Después de las instalaciones el archivo package.json
debería tener un contenido similar a
// package.json
{
"name": "pythontest",
"version": "0.0.1",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-watch": "^0.6.1"
}
}
Y se ha creado un directorio llamado node_modules
que contiene las dependencias.
Definición de tareas
Para la configuración de grunt y definición de tareas es necesario crear el archivo Gruntfile.js
module.exports = function(grunt){
grunt.initConfig({
watch: {
grunt: {
files: ['Gruntfile.js']
},
python: {
files : ['./tests/*.py','./libs/*/*.py'],
tasks: ['pythontest'],
},
}
});
grunt.registerTask('pythontest', function(){
grunt.util.spawn({
cmd: 'python',
args: ['setup.py','test'],
opts: {stdio: 'inherit'},
});
});
grunt.registerTask('default', ['watch']);
};
Y lanzar grunt
grunt
Con lo cual, cada vez que un archivo definido en files
sea modificado será ejecutada la tarea pythontest
que lanza los test.
La opción opts: {stdio: 'inherit'}
permite que la salida del comando ejecutado sea mostrada, sin esto, python setup.py test
sería lanzado pero no visualizado el resultado.
Archivos modificados en git
Otra cosa que verifico son los archivos agregados a git.
git status
Por lo que también me es útil agregar una tarea que se ejecute cada vez que se modifica el index de git .git/index
.
gitindex: {
files : ['.git/index'],
tasks: ['gitst'],
},
Y registrar la tarea
grunt.registerTask('gitst', function(){
grunt.util.spawn({
cmd: 'git',
args: ['status'],
opts: {stdio: 'inherit'},
});
});
Conclusión
Con lo descrito anteriormente es posible dejar a grunt en una terminal independiente vigilando que archivos son modificados y lanzando tareas previamente definidas.
Herramientas como grunt permiten reducir el tiempo utilizado en tareas repetitivas y enfocarse en el ciclo de desarrollo.
El código final de Gruntfile.js
y package.json
está alojando en un gist de github.