En esta publicación
voy a explicar cómo implementar la base para un proyecto o librería
que queramos desarrollar con TDD + DDD utilizando Composer desde
cero.
Para desarrollar con
TDD vamos a necesitar un framework de pruebas. En este caso se va a
utilizar PHPUnit
que es un framework de pruebas muy extendido. Para instalar los
paquetes como PHPUnit
disponemos de varias herramientas siendo Composer
de las más comunes.
Otro problema al que
nos enfrentamos a la hora de llevar a cabo el proyecto es la
configuración del fichero de composer para que todo funcione
correctamente. Así que voy a explicar cómo llevar a cabo cada paso
para tener un proyecto desarrollado con TDD + DDD con Composer.
Por supuesto, el
control de versiones es imprescindible en cualquier proyecto así que
en este caso se va a utilizar Git.
Lo primero es crear
una carpeta con el nombre del proyecto. Así que, suponiendo que
tenemos una carperta “projects” en nuestra home de usuario, desde
una consola creamos la carpeta con el nombre del proyecto, por
ejemplo: “php-tdd-ddd-template-composer”.
mkdir ~/projects/php-tdd-ddd-template-composer
|
Una vez creada
accedemos a ella.
cd
~/projects/php-tdd-ddd-template-composer
|
Ahora hay que
iniciar un proyecto en Git. Así que creamos nuestro flamante
proyecto en git con el siguiente comando.
git init
|
Siempre es
recomendable añadir un archivo README.md ya que tanto para otros
usuarios como para nosotros mismo en un futuro nos va a ser útil. No
hay un estándar para hacer ficheros de este estilo aunque seguro que
con una rápida búsqueda puedes encontrar recomendaciones o
plantillas.
Una vez creado el
archivo README.md lo incluimos en el repositorio.
git add .
|
Hacemos “commit”
del mismo.
git commit -m “Add README.md” file.
|
Creado el proyecto y
el repositorio, el siguiente paso es crear un archivo de composer
para que sea más fácil la administración de los distintos
paquetes.
composer init
|
Este comando va a
crear una serie de preguntas
Package name (<vendor>/<name>)
[eltortuganegra/php-tdd-template-composer]:
Description []: Template for php
projects for develop with TDD. Composer is used for install
project.
Author [, n to skip]: Jorge Sánchez
<jorge.sanchez@eltortuganegra.com>
Minimum Stability []:
Package Type (e.g. library, project,
metapackage, composer-plugin) []:
License []: MIT
Would you like to define your
dependencies (require) interactively [yes]?
Search for a
package:
Would you
like to define your dev dependencies (require-dev) interactively
[yes]? Yes
Search for a package: phpunit
Found 15 packages matching phpunit
[0] phpunit/phpunit
[1] phpunit/phpunit-mock-objects
[2] phpunit/php-token-stream
[3] phpunit/php-timer
[4] phpunit/php-text-template
[5] phpunit/php-file-iterator
[6] phpunit/php-code-coverage
[7] symfony/phpunit-bridge
[8] phpunit/phpunit-selenium
[9] johnkary/phpunit-speedtrap
[10]
codedungeon/phpunit-result-printer
[11]
jean85/pretty-package-versions
[12] brianium/paratest
[13] phpunit/dbunit
[14]
spatie/phpunit-snapshot-assertions
|
Los paquetes que
vamos a instalar son, de momento, phpunit en su última versión.
En este caso
añadimos un 0 y pulsamos enter, lo que nos lleva a buscar otro
paquete. Como no queremos añadir más paquetes. Pulsamos enter.
Para ver las
dependencias escribimos “yes” y pulsamos enter.
Search for a package:
{
"name": "eltortuganegra/php-tdd-template-composer",
"description": "Template for php projects for
develop with TDD. Composer is used for install project.",
"type": "project",
"require-dev": {
"phpunit/phpunit": "^7.3"
},
"license": "MIT",
"authors": [
{
"name": "eltortuganegra",
"email": "jorge.sanchez@eltortuganegra.com"
}
]
}
Do you confirm generation [yes]? yes
Would you like the vendor directory added to your .gitignore
[yes]? yes
|
Sólo queda
confirmar y se procede a la generación del archivo “composer.json”.
Ahora pasamos a
instalar con composer todas las dependencias.
composer install
|
En este momento se
puede observar como se ha creado una carpeta «vendor» donde se han
instalado todas las dependencias.
Llega el momento de
organizar las distintas carpetas del proyecto. Cada uno tiene su
organización de carpetas pero una buena manera de empezar es crear
una carpeta «tests» y otra «src» donde se almacenará el código
de los tests (sí, ¡las pruebas se hacen primero!).
Para comprobar si
Phpunit está funcionando vamos a crear una prueba por defecto:
DefaultTest.php
Cuando ejecutamos
phpunit para que ejecute la prueba
./vendor/bin/phpunit tests/DefaultTest.php
|
Debería devolver el
siguiente resultado.
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
. 1
/ 1 (100%)
Time: 98 ms, Memory: 4.00MB
OK (1 test, 1 assertion)
|
Con esta sencilla
prueba se verifica que Phpunit está funcionando correctamente. Aún
que el propósito es probar el código fuente así que vamos a añadir
una prueba donde se utilice una clase que esté ubicada en la carpeta
destinada a tal fin, la carpeta «src».
Una prueba simple
podría ser crear una instancia de la clase ubicada en la carpeta
«src» y comprobar que la nueva instancia es una instancia de esa
clase.
Ejecutamos la prueba
recién creada para confirmar que da un error, tal y como se indica
en TDD.
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
.E 2
/ 2 (100%)
Time: 83 ms, Memory: 4.00MB
There was 1 error:
1)
DefaultTest::testDeleteMeShouldCreateAnInstanceWhenWeCreateAnInstance
Error: Class 'DeleteMe' not found
/home/vagrant/www/php-tdd-template-composer/tests/DefaultTest.php:17
ERRORS!
Tests: 2, Assertions: 1, Errors: 1.
|
Como se puede
apreciar la ejecución de la prueba da un error. Ahora hay que crear
la clase “DeleteMe” en la carpeta «src» para que pasar la
prueba. Añadimos el namespace «app».
En este caso, si
volvemos a ejecutar la prueba vamos a tener el mismo error. ¿Cómo
es posible si hemos creado la clase? El problema es que no estamos
indicando que cargue las clases automáticamente. Para configurarlo
hay que modificar el fichero de configuración de composer y
añadirle un atributo “autoload”.
{
"name": "eltortuganegra/php-tdd-template-composer",
"description": "Template for php projects for
develop with TDD. Composer is used for install project.",
"type": "project",
"require-dev": {
"phpunit/phpunit": "^7.3"
},
"license": "MIT",
"authors": [
{
"name": "eltortuganegra",
"email": "jorge.sanchez@eltortuganegra.com"
}
],
"autoload": {
"classmap": [
"src/"
]
}
}
|
Actualizamos
composer para que incorpore los cambios en el fichero de
configuración.
composer dump-autoload
|
Y volvemos a
ejecutar la prueba. Con el siguiente resultado.
./vendor/bin/phpunit tests/DefaultTest.php
PHPUnit 7.3.5 by Sebastian Bergmann and contributors.
.. 2
/ 2 (100%)
Time: 67 ms, Memory: 4.00MB
OK (2 tests, 2 assertions)
|
Llegados a este
punto, tenemos la base del proyecto funcionando. Una carpeta «tests»
donde se almacenan todos las pruebas y una carpeta «src» donde se
almacena todo el código que tiene que pasar las pruebas.
Según el DDD no hay
una organización estándar de estructuras así que cada uno es libre
de organizarla como considere oportuno. En el libro de Eric Evans
Domain-Driven Design book tiene un ejemplo “Cargo Sample” del
cual se puede encontrar implementaciones en GitHub como como el
php-ddd-cargo-sample.
En el se puede apreciar la estructura de carpetas que utilizan.
Sin embargo, esta
publicación es para crear un proyecto sencillo y de cero por lo que,
en principio y como ejercicio paso a paso, crearía una carpeta por
cada concepto que se detalla en DDD.
Mi solución
sencilla para aquellos que están empezando y quieren empezar a
introducirse en este mundo es utilizar la plantilla
para proyectos en php con TDD y DDD.
En esta plantilla hay una estructura de carpetas que albergan un clase por defecto por cada concepto y su correspondiente prueba en la carpeta «tests».