Desarrollo Guiado por Pruebas en Laravel: Configuración y Ejecución
Resumen
¿Qué es el desarrollo guiado por pruebas (TDD)?
El desarrollo guiado por pruebas, conocido como TDD por sus siglas en inglés (Test-Driven Development), es un enfoque de programación que, comparado con la metodología tradicional, cambia la manera en la que desarrollamos software. Aquí, empezamos escribiendo una prueba antes de desarrollar cualquier funcionalidad. Esta prueba guía el desarrollo hasta lograr un código correcto. A diferencia de programar directamente y corregir errores directamente en el navegador, TDD nos permite centrarnos en asegurar que cada pequeña parte del código hace exactamente lo que debe.
¿Cómo comenzar con TDD en Laravel?
En Laravel, el primer paso para implementar TDD es configurar una prueba para el método que deseas desarrollar. En este caso, se trata del método store para una API que permite guardar datos mediante una solicitud POST en formato JSON. La prueba se encargará de:
Conectar correctamente la aplicación con la ruta definida.
Comprobar que los datos enviados están siendo almacenados adecuadamente.
Verificar que la estructura JSON retornada corresponde a lo planificado.
Asegurarse de que el estado HTTP devuelto, en este caso un 201, refleja la correcta creación del recurso.
Código de ejemplo para pruebas
El contenido del test podría verse así:
publicfunctiontest_debe_guardar_un_post(){$response=$this->postJson('/api/posts',['title'=>'Post de prueba',]);$response->assertStatus(201)->assertJson(['title'=>'Post de prueba','created_at'=>true,'updated_at'=>true,]);$this->assertDatabaseHas('posts',['title'=>'Post de prueba']);}
Configurando la base de datos para el test
Debes asegurarte que tu base de datos de pruebas tenga la estructura necesaria, como la tabla posts con el campo title. Utiliza migraciones para configurar la estructura que desea verificar en tu prueba.
¿Cómo escribir código para pasar las pruebas?
Tras definir tus pruebas, es hora de desarrollar el código necesario para cumplirlas. Podrías implementar el método store en un controlador de la siguiente manera:
Este código espera recibir un conjunto de datos, guardarlos en la base de datos, y devolver una respuesta JSON con el nuevo recurso creado. Siempre es posible ajustar la función para que cumpla con todos los requisitos de la prueba.
¿Qué hacer ante errores en las pruebas?
Los errores en las pruebas son sumamente útiles; te indican exactamente qué parte de tu código no se ajusta a las expectativas. Por ejemplo, si la prueba indica que una ruta no funciona, verifica que esté correctamente definida:
Usando comandos de Laravel, se puede listar las rutas actuales y verificar que todas estén correctamente configuradas.
¿Por qué elegir TDD?
Optar por TDD asegura que tu código tenga alta calidad y sea mantenible a largo plazo. Cada modificación futura estará respaldada por pruebas que garantizarán que nuevas implementaciones no quiebren el código existente. Además, centraliza el enfoque en la funcionalidad principal desde el comienzo del desarrollo.
Este método es particularmente poderoso en Laravel, donde la integración con PHPUnit facilita la escritura y ejecución de pruebas. ¡No dudes en continuar profundizando en TDD y perfeccionar tus habilidades como desarrollador!
Si usan laravel en su versión 7.3 en adelante pueden utilizar el comando php artisan test en lugar de vendor/bin/phpunit . El comando artisan test les proveera mas información y una interfaz mas amigable.
Gracias!!!
También pueden crear un alias en la terminal, yo por ejemplo lo corro con phpunit, si tienen szh puede configurarlo así:
alias phpunit="vendor/bin/phpunit"
could not find driver
Si les aparece un error de este tipo :
failed Illuminate\Database\QueryException
could not find driver (SQL: PRAGMA foreign_keys = ON;)
La solución que me funcionó fue ejecutar el comando :
sudoapt-getinstall php-sqlite3
😁😁😁😁
Gracias por la ayuda, tenia el mismo problema
Gracias, tengo el mismo problema, pero instale lo que decis y no me funciona
Si les llega a mandar error en las rutas al ejecutar el listado de las mismas:
Targetclass[Api\PostController] does not exist.
En Laravel 8 se tiene que utilizar el Fully Qualified Class Name, o sea, toda la ruta del controlador:
Tambien lo puedes declarar arriba, al principio del documento
use App\Http\Controllers\Api\PostController;use Illuminate\Support\Facades\Route;Route::apiResource('post',PostController::class);```
Gracias por la aclaracion
Si tiene dudas de los códigos de status les dejo una página que me ayudo mucho
Http Status
Si terminas la clase y muestra que tienes problemas con los archivos relacionados con Database al hacer el test, pues así lo solucioné yo:
Abrí el archivo php.ini haciendo click en el menu de Laragon -> PHP -> php.ini. Si usas alguna otra herramienta buscalo en tu carpeta de xamp o apache2.
Busque la palabra sqlite para ir a la linea donde estaba declarado.
En mi caso estaba comentado, asi que lo descomenté y guardé.
lluminate\Database\QueryException: could not find driver (SQL: PRAGMA foreign_keys = ON;)
Este problema es ocasionado por el driver de sqlite que desde PHP5.0 ya viene integrado pero el modulo esta des habilitado entonces solo tienes que modificar el archivo php.ini de la siguiente forma:
//'encuentra la siguiente linea' ;extension=pdo_sqlite
//'quita el ; que tiene al inicio, guarda el archivo y reinicia tu servidor local'extension=pdo_sqlite
Una vez realizado lo anterior, los test se ejecutan sin problema.
Espero que esto les ayude :)
Gracias compañero. Me has ayudado!
PARA LARAVEL 8
Si después de correr las pruebas te pone "Unknow database laravel" es porque está usando por defecto la base de datos real, lo cual no es correcto, debemos mantener nuestra base de datos real separado de la base de datos de testing, ya que la base de datos de testing realizará pruebas y refrescará la base de datos, etc.
El error se debe a que en Laravel 8, las lineas del driver de la base de datos vienen comentadas en el archivo phpunit.xml, lo único que tienen que hacer es descomentarlas para que puedan correr su prueba.
Si después de da error por el driver, abajo hay algunas aportaciones explicándote cómo resolverlo, si estás trabajando con Ubuntu y tienes apache instalado por tu parte, debes instalar la extensión para sqlite: sudo apt-get install php7.4-sqlite
Si despues de hacer esto sigue mostrando el mismo error, limpia la cache con:
php artisan config:cacache
e intenta de nuevo.
$this->withoutExceptionHandling(); no muestra un detalle mas amplio del error
Store con TDD
Los métodos dentro de la clases de pruebas siempre tienen que comenzar con test y underscore, así:
publicfunctiontest_store(){}
En el siguiente caso estamos accediendo a la ruta '/api/posts' y enviamos el dato Array que le sigue. Después, cuando eso suceda el sistema tiene que retornar en un sistema JSON dentro de un Array los datos en la última sentencia y comprobar que tenga el Array que enviamos con anterioridad.
classPostControllerTestextendsTestCase{publicfunctiontest_store(){$response=$this->json('POST','/api/posts',['title'=>'El post de prueba']);$response->asserJsonStructure(['id','title','created_at','updated_at'])->assertJson(['title'=>'El post de prueba'])->assertStatus(201);//Status OK, se a creado un recurso// Para saber si existe este dato en la Databse$this->assertDatabaseHas('posts',['title'=>'El post de prueba']);}}
Si les sale el siguiente error al ejecutar PHPUnit:
could not find driver(SQL:PRAGMA foreign_keys =ON);
Tienes que instalar la extensión de sqlite, este es el comando para ubuntu:
sudoapt-getinstall php-sqlite3
Podemos realizar tambien lo siguiente ni no queremos usar la iniciación test_
Ejemplo:
/**@test*/
public function can_create_user() {/*Aqui va mi código*/}
Para los que trabajan desde Windows, en la versión de php 7.2.5
les saldrá el siguiente error:
There was 1error:1)Tests\Feature\Http\Controllers\Api\PostControllerTest::test_store
Illuminate\Database\QueryException:could not find driver(SQL:PRAGMA foreign_keys =ON;)
Este error se soluciona de la siguiente manera:
Navega hasta la ruta donde tienes php instalado
C/php/php.ini
Una vez encuentres el archivo "PHP.INI" con tu editor favorito vas a modificar las siguientes líneas de código:
909|;extension=pdo_sqlite
Eliminar el punto y coma ( ";" )
909| extension=pdo_sqlite
Debes hacer lo mismo en la siguiente linea de codigo:
919|;extension=sqlite3
Eliminar el punto y coma ( ";" )
919| extension=sqlite3
Y listo ya te debe funcionar bien el comando php:
php vendor/phpunit/phpunit/phpunit
Muchas gracias, me fue de gran ayuda!
Pregunta, lo que pasa es que me sale el siguiente error al ejecutar vendor/bin/phpunit:
Illuminate\Database\QueryException: could not find driver (SQL: PRAGMA foreign_keys = ON;)
Indague y ya active las extensiones de sqlite, reinicie el servidor, pero nada, me sigue saliendo el mismo error, no se si alguien sea tan amable de colaborarme a ver como más se puede solucionar, estoy usando windows.
Hola Andrés. Este error se debe a que no está habilitado sqlite en el archivo php.ini. Debe activarlo ingresando a php.ini y eliminar los comentarios en sqlite y sqlite3.
extension=pdo_sqlite
extension=sqlite3
Luego reiniciar el servidor web nuevamente.
En Laravel 8.x me funciono así en las rutas:
use App\Http\Controllers\Api\PostController;Route::apiResource('/api/posts',PostController::class);```
Pase días intentando solucionar esto
could not find driver(SQL:PRAGMA foreign_keys =ON);
La solución era simple y la vi por todos lados, pero por una confusión nunca lo intente.
.
Yo uso laragon y lei que debía activar las extensiones de sqlite en laragon, lo hice, pero seguía sin funcionar. La cuestión es que los test no corren en el servidor web, corren en local y estaba ejecutando los test en la consola de ubuntu, donde no tenia las extensiones, esa fue mi confusión. Laragon activa las extensiones en windows mas no en ubuntu.
.
Conclusión:
Si usas una terminal de windows solo activa las extensiones y asegúrate de que estas ejecutando la versión de php de laragon.
Si usas ubuntu ejecutar el comando sudo apt-get install php-sqlite3 y con eso deberia bastar.
.
Espero que no tengan que pasar por lo que yo pasé para aprender esto 😂💚
Muchas gracias compañero! 💚
¿Cómo puedo hacer un test a un archivo en específico? digamos php artisan test y luego que mas?? xfa chicos
Corriendo:
phpunit --filter <El Nombre del archivo del test>
Lo que puedes hacer es correr
php artisan test --filter <nombre_del_archivo>
Por si a alguien le sirve esto para el futuro, alguien que esté trabajando con Laravel 8, como yo:
En el archivo api.php, me funcionó de la siguiente manera:
publicfunctiontest_store(){ $this->withoutExceptionHandling(); $response = $this->postJson('/api/posts',['title'=>'El post de prueba']); $response->assertJsonStructure(['id','title','created_at','updated_at'])->assertJson(['title'=>'El post de prueba'])->assertStatus(201); $this->assertDatabaseHas('posts',['title'=>'El post de prueba']);}
genial, me sirve tambien en laravel 9
Los Test son guías para hacer un codigo correcto
You tuve el error de
Failed asserting that an array has the key 'id'.
Y usaba la fucion para ver los errores pero salia lo mismo y lo que estaba mal era la funcion para
crear el registro el mio era
$post =Post::created($request->all());
y era para hacer
$post =Post::create($request->all());
pero lo que no llego a comprender porque no me salia el error de la funcion al go asi como que no existe estuve revisando buen tiempo hasta que di con el error.
Alguno hizo instalacion en WSL2 , y corre sus archivos dentro del sistema de archivos de linux? a mi no me deja abrir la base de datos SQLITE
• Tests\Feature\Http\Controllers\Api\PostControllerTest > store
Illuminate\Database\QueryException
SQLSTATE[HY000] [14] unable to open database file (SQL: PRAGMA foreign_keys = ON;)
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:678
674▕ // If an exception occurs when attempting to run a query, we'll format the error
675▕ // message to include the bindings with SQL, which will make this exception a
676▕ // lot more helpful to the developer instead of just the database's errors.
677▕ catch (Exception $e) {
➜ 678▕ throw new QueryException(
679▕ $query, $this->prepareBindings($bindings), $e
680▕ );
681▕ }
682▕