Desarrollo Guiado por Pruebas en PHP: Creación de Clases y Métodos
Resumen
¿Cómo llevar una prueba de rojo a verde en el desarrollo guiado por pruebas?
El desarrollo de software a menudo enfrenta el desafío de garantizar que las funcionalidades cumplan con las expectativas del usuario. Adoptar el desarrollo guiado por pruebas o Test-Driven Development (TDD) es una práctica que asegura que cada línea de código esté justificada por pruebas previas. Al comenzar con una prueba que falla (roja) y realizar los cambios necesarios para que pase (verde), podemos mejorar nuestro proceso de desarrollo.
¿Cómo iniciamos la creación de clases?
Inicialmente, hemos identificado que uno de los errores principales al ejecutar el comando es que la clase app\post no existe. Para rectificar este problema:
Creamos un directorio llamado src, definido en nuestro archivo composer.json.
Dentro de este directorio, creamos el archivo Post.php para comenzar a desarrollar la clase post.
Con esto en mente, es esencial asegurarnos de que la clase esté declarada correctamente y que incluya un espacio de nombres (namespace) adecuado para evitar errores de ejecución.
¿Cuál es el rol de los comentarios y métodos en nuestro código?
Una vez que hemos resuelto el problema de la existencia de la clase post, encontramos otro obstáculo: la ausencia del método addComment. Para abordar este problema:
Creamos un archivo Comment.php que contiene la definición de la clase Comment.
En la clase Post, implementamos el método addComment. Este método se asegura de recibir un parámetro que es una instancia de la clase Comment. Esto garantiza que los comentarios añadidos sean válidos y pertenezcan al mismo espacio de nombres.
Este enfoque también implica la creación de una propiedad denominada comments dentro de la clase Post, que inicialmente es un arreglo vacío. De esta manera, podemos agregar comentarios y acumularlos adecuadamente.
¿Cómo implementamos el conteo y la obtención de comentarios?
Para expandir la funcionalidad de la clase Post, incorporamos métodos adicionales que permiten contar y obtener comentarios:
Este método devuelve todos los comentarios almacenados en la propiedad para que puedan ser manipulados externamente.
¿Qué sucede si enviamos un string en lugar de un objeto comment?
En los momentos finales, integramos validaciones adicionales para enfatizar la importancia de trabajar con instancias de objetos y no con tipos de datos básicos como strings. Al ejecutar un test con un string en lugar de la instancia esperada, observamos que el código amablemente avisa de que no es la instancia esperada.
La validación de tipos en la implementación bloquea estos errores, priorizando instancias específicas de nuestras clases. Así, conseguimos proporcionar múltiples niveles de seguridad, tanto a nivel de prueba como a nivel de código.
En el ámbito del desarrollo software, este ciclo de crear pruebas, escribir código a partir de ellas y refactorizar contribuye decididamente a elevar nuestras habilidades de programación a nivel profesional. Las pruebas aseguran que cualquier modificación futura no altere el comportamiento deseado, brindando una base sólida para el crecimiento y mantenimiento del código.
En esta clase se mencionó algo muy importante, y es el tipo de dato que se espera, cuando trabajamos con parámetros en las funciones es posible especificar qué tipo de dato estamos esperando, esto hace que sea un código mejor estructurado y te acerca más a las buenas prácticas, de igual manera, los métodos de las clases pueden especificar qué tipo de dato se va a retornar, así le confirmamos 100% a quien use nuestra clase que vamos a retornarle si o si tal tipo de dato, por ejemplo, en esta clase:
<?php
namespace App;classComment{public $like_count =0;publicfunctionlike(User $usuario): int {return $this->like_count;}}?>
Vemos que hay un método que espera como parámetro "User $usuario", esto quiere decir que, el parámetro $usuario tiene que ser si o si una instancia de la clase Usuario, si yo reemplazara "User" por "string" le estarían diciendo que espero que el parámetro $usuario sea una cadena de texto.
De igual manera, es función tiene al final " : int" esto está diciendo que el método va a devolver si o si un entero, de esta manera podemos hacer un código más robusto y a prueba de errores.
Muy buen aporte
Excelente aporte
Si te te sale un error: Error: Class 'App\Post' not found a pesar de haber creado la clase y el namespace, ejecuta composer dump-autoload, esto hara que la clase que sea reconocida por el autoload y no mostrara el previo error.
Muchas gracias.
genial, esa fue la solución
Hola, en mi caso al configurar phpunit en composer utilizó la versión 10.0 y para realizar los test no funcionan con el comando:
vendor/phpunit/phpunit/phpunit
Revisando la documentación se debe usar:
vendor/bin/phpunit
y con ello pude seguir la clase.
Gracias Compa
Cuando ya se tiene mas practica y mas conocimiento en el desarrollo de software, siempre te vas a ir por escribir codigo primero y luego los tests, con esto quiero decir que, aunque en la teoria sea lo contrario, esta es la realidad
Estas en lo cierto, viendo estas dos clases, pensaba en que forma podría cambiar mi forma de desarrollar. Difícil ...
Yo tengo ya la experiencia escribiendo test y para ser sincero, siempre escribo mi test y luego código 🤔, lo que NO hago, es caer en cada error del test, si no, escribir todo mi código y luego correr el test, cuando escribi mi código, estoy cubriendo ya varios "errores básicos".
🔮 Quieres optimizar tu tiempo de desarrollo y garantizar la calidad del código entonces es momento de utilizar TDD.
tengo este error. ayuda.
¿Lo solucionaste?
¿Tienes bien configurado tu XML?
Al hacer la prueba con phpunit me sale el siguiente error:
There was 1error:1)PostTest::test_add_comment_to_post
Undefined variable: comments
Y al revisar la variable me sale la siguiente advertencia:
Yo entiendo que no detecta que la $this->comments ya ha sido inicializada mas arriba.
He estado intentando varias cosas sin resultado y no se si a alguien mas tiene el mismo problema.
Debes hacerlo así $this->comments[] = $comment;.
Como lo tienes en este momento es como si le dijeras a PHP "Dame la propiedad de $this que se llama como el valor que tengo guardado en la variable $comments" cuando lo que le quieres decir es "Dame la propiedad de $this que se llama comments"
Muchas gracias @elbunuelo, no puedo creer que haya perdido muchas horas de mi vida con un error tan tonto.
Hasta ahora ha sido la mejor explicación de TDD para PHP. Muchas gracias profe!
Haciendo el curso en marzo del 2024, al ejecutar el comando php vendor/phpunit/phpunit/phpunit no pasa nada, buscando en la documentación y con ayuda de otros comentarios llegue a una solución por lo menos con la version 10.5.15 que es la que estoy usando:
se debe ejecutar el comando php vendor/bin/phpunit tests/PostTest.php
Espero que les sea de ayuda
Hola me genera este error:
There was 1error:1)PostTest::test_add_comment_to_post
Error:Class'App\Post' not found
C:\xampp\htdocs\Data\PHP\CursoPlatzi\POO\Proyecto\tests\PostTest.php:10
La linea 10 hace referencia a $post = new Post();
use PHPUnit\Framework\TestCase;use App\Post;use App\Comment;classPostTestextendsTestCase{publicfunctiontest_add_comment_to_post(){ $post =newPost();//Se crea un post aqui es el error $comment =newComment();//Se crea un comentario $post->addComment($comment);//Ese comentario se agrega al post $this->assertEquals(1, $post->countComments());// $this->assertInstanceOf(Comment::class, $post->getComments()[0]);//Si esta instanciado, correcto}}
¿Alguien más tuvo este error?
Yo también tuve este error en Windows, lo que hice fue registrar la carpeta test en el archivo composer.json, quedaría de la siguiente manera:
{"name":"cristianbastos/post","description":"Proyecto de POO","autoload":{"psr-4":{"App\\":"src/"}},"autoload-dev":{"psr-4":{"Test\\":"test/"}},"require-dev":{"phpunit/phpunit":"^9.4"}}
Luego ejecuté en la consola :
composer dump
y listo, ya pude ver que no faltaba la clase Post, sino que faltaba la clase Comment, obviamente porque no la había creado, pero se veía que ya había pasado el error que no encontraba la clase Post.
Y ejecuto en la consola para php unit, ubicado desde la raíz del proyecto:
php vendor/phpunit/phpunit/phpunit
Por qué el profesor no tuvo que agregar esa parte de código del autoload del test en su ejercicio?
El desarrollo guiado por pruebas (TDD) en PHP implica crear pruebas antes de escribir el código. Comienzas definiendo una prueba que falle (rojo), luego implementas el código necesario para que pase (verde). En la clase mencionada, se crea una clase Post y se implementan métodos como addComment, countComments y getComments, asegurando que la lógica se alinee con las pruebas. Esto fomenta un código más robusto y menos propenso a errores, facilitando su mantenimiento y mejora.
A esto se le llaman pruebas unitarias?
Hola, desde la finalizacion de la clase pasada cuando ejecuto php unit no me genera el test, se carga una lista de comandos php unit.
Comprueba que estás ejecutando bien el comando; php vendor/phpunit/phpunit/phpunit (si estás en Windows)
Ayudita, no me carga directamente el test usando el xml como referencia
Gracias por tu respuesta pero no, tengo que usar phpunit y decirle el archivo del proyecto.
Me da el sigueinte error, alguien sabe como solucionarlo? lo peor es que me dice "audoload" y el archivo es "autoload"; el archivo esta bien escrito, nose porque en la terminal aparece como "audoload"
PHPUnit 10.1.3 by Sebastian Bergmann and contributors.
Cannot open bootstrap script "/home/max/Documentos/platzi/Curso de Programación Orientada a Objetos en PHP/05 Proyecto/vendor/audoload.php"
A pesar de tener el mismo código, el test no pasa de:
Error:Class"App\Post" not found
Y realmente el código de error no es explícito, no sé por qué no lo encuentra, pues según el proceso descrito por el profesor está bien, pero el test no pasa de ahí.
¡Hola!, no sabría decirte exactamente qué pasa, por lo que te dejaré algunas recomendaciones:
Revisa que la configuración en Composer esté correcta, específicamente el Autoload, y recuerda usar composer dump
Revisa que en la clase Post estás usando namespace App
Es lo único que se me ocurre por ahora ¡Mucha suerte!
En la terminal utliza el comando cponser dum
Ayuda please, me sale este error en la terminal, ya revise el codigo y no entiendo porque me sigue dando error.
Hola es que en tu codigo de Post.php tienes error en la funcion countComments y getComments. El this lo estas apuntando como si recibiera un parametro, pero debe de quedar asi:
publicfunctioncountComments(){returncount($this->comments);// ese comment tu lo tienes $comments, // pero es sin el signo de dolar}
Y lo mismo para getComments()
Wow solo eso jaja, muchas gracias me funciono
¿Alguien sabe por qué no me ejecuta la prueba? Tengo todo tal cual lo tiene el profesor y en la terminal solo me sale:
No tests executed
revisa el xml, seguro no le estas mandando bien la carpeta de los test