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.
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.
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.
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'},
});
});
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.