Levanta rápido una API de productos en Laravel usando SQLite, migraciones, TDD, Faker, model factories y seeders. Sin servidores extra ni configuraciones complejas: configura la base de datos, genera datos de prueba y valida con tests automatizados. Ideal para un flujo ágil y confiable.
¿Cómo configurar SQLite en Laravel sin servidor?
Configurar una base transaccional liviana con SQLite evita instalar y levantar servicios. Laravel trae el driver listo y se activa con unos ajustes mínimos.
¿Qué cambiar en .env y en config database.php?
Crear el archivo de base: database/database.sqlite.
En .env, ajustar la conexión: DB_CONNECTION=sqlite.
Si existe DB_DATABASE, borrarla para usar el archivo por defecto.
Confirmar en config/database.php: el driver sqlite usa database/database.sqlite si no hay DB_DATABASE.
¿Cómo ejecutar migraciones con php artisan migrate?
Bajar el servidor, luego correr migraciones.
php artisan migrate
Si aparece que la BD no existe: eliminar DB_DATABASE en .env y repetir el comando.
Ver tablas creadas con el cliente de PHPStorm: Tools > Database, elegir SQLite y abrir database/database.sqlite. Probar conexión: debe decir que está OK.
¿Cómo generar datos de prueba con Faker, factories y seeders?
Para trabajar la API, se requieren registros confiables y repetibles. Aquí entran Faker, model factories y seeders.
¿Qué hace un model factory con Faker?
Un factory define cómo generar datos falsos realistas.
En database/factories, ajustar el factory de producto:
nombre: con Faker, un nombre al azar.
precio: un número entre diez mil y sesenta mil.
Resultado: valores aleatorios coherentes para pruebas.
¿Cómo se ejecuta un seeder para poblar la base?
En ProductSeeder, usar el factory del modelo para crear N registros y create para insertarlos.
En DatabaseSeeder, llamar a ProductSeeder para centralizar su ejecución.
Poblar la base de datos:
php artisan db seed
Se puede correr varias veces para generar más productos. Verificar en el cliente de base que se inserten registros aleatorios.
¿Cómo construir y probar la API de productos con TDD?
La técnica TDD guía el desarrollo: primero fallan los tests, luego se implementa lo mínimo para hacerlos pasar. Así se asegura funcionalidad y cobertura desde el inicio.
¿Qué crear con make model y controlador API?
Al fallar por “no existe la clase producto”, generar el modelo:
php artisan make model product
Además, incluir controlador de tipo API y todos los artefactos necesarios con la flag de “all”: migración, factory, seeder y controlador.
En la nueva migración, definir columnas de products como nombre (string) y precio (float); luego migrar para crear la tabla.
¿Cómo funcionan index, store, show, update y destroy?
index: listar todos los productos con Eloquent y retornarlos.
store: crear con Product::create(...) usando los atributos de la petición.
show: gracias a la inyección de dependencias, recibe el modelo y lo retorna.
update: actualizar el recurso con update(...) desde la petición.
destroy: eliminar el producto y responder en JSON con 200.
Asignación masiva: en el modelo Product, declarar protected $guarded = []; para permitir crear/actualizar con cualquier atributo permitido.
¿Cómo declarar rutas y verificar con row list?
En routes/api.php, definir una ruta tipo recurso con la URI products apuntando al controlador.
Listar rutas registradas:
php artisan row:list
Tests de integración: crear 5 productos, llamar la ruta y verificar que la cantidad devuelta coincida. Al ejecutar todos, se reportan 5 tests y 10 assertions, lo que confirma la configuración.
Habilidades y conceptos reforzados en este flujo:
Configuración de SQLite en Laravel sin servidor adicional.
Manejo de variables de entorno en .env para la conexión de BD.
Migraciones para versionar esquemas.
Generación de datos con Faker vía model factories y seeders.
Diseño de API REST con controlador de recursos.
Asignación masiva y uso de $guarded.
Inyección de dependencias en métodos del controlador.
Pruebas de integración con TDD para endpoints.
Ruteo de recursos y consulta de rutas con comandos de Artisan.
¿Te animas a replicarlo con un modelo Category? Crea su model, factory, seeder, migration y su endpoint para crear y listar categorías. Cuéntame en comentarios cómo te fue y qué dudas te surgieron.
Para los que usen Visual Studio Code, existe una extensión llamada SQLite, que nos permite visualizar la base de datos y ejecutar queries desde el editor.
una pregunta compañero, cómo haces para que la extensión te permita visualizar los archivos .sqlite? yo ya la instale pero mi archivo se sigue viendo con binarios.
Esta es la ext y podemos ejecutar los query desde allí
Para ejecutar los tests, para aquellos que no tengan phpstorm, lo pueden ejecutar desde la consola en la raíz del proyecto con el comando:
php artisan test
O también pueden ejecutar directamente php unit con el siguiente comando:
vendor/bin/phpunit
Además si quieren ver mejor la salid de esta forma, pueden agregar el parámetro --testdox
vendor/bin/phpunit --testdox
php artisan test
esto funciona solo en laravel ^7.0
muchas gracias por el aporte
En Laravel 8, los models factories cambian, ahí se debe usar:
Product::factory(5)->create()
Y para usar faker en un archivo de Factory debes accederlo mediante $this : $this->faker->name
Les dejo los archivos completos de esta clase en este commit:
Hola consulta, vi en tu código test que al método test_index de ProductController justo en el método assertJsonCount, aparte de que te cuente los registros, le pasas el parámetro key como "data", al menos por mi parte me da un error, entonces quiero saber que estoy haciendo mal.
Para que me funcionara solo debí omitir la key, pero quiero entender si es algo que yo estoy haciendo mal.
El parámetro "data" se utilizará más adelante.
En laravel una API se trabaja con una capa de transformación que se llama "Resource" en los próximos videos el profesor explicará sobre ese tema, lo que hace es convertir un modelo o colección de modelos Eloquent en Json. Por el momento no le coloques el argumento "data".
Ese parámetro es un json que contiene lo siguiente:
A mi me daba error al migrar
Illuminate\Database\QueryException
could not find driver (SQL: PRAGMA foreign_keys = ON;)
La solución
sudo apt-get install php-sqlite3
Solucionó mi migración! buenisimo
Usando Laravel 8, el sistema de rutas tambien varia, por lo que en nuestro archivo routes/api.php quedaria asi:
use App\Http\Controllers\ProductController;use App\Http\Controllers\CategoryController;use Illuminate\Http\Request;use Illuminate\Support\Facades\Route;/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/Route::middleware('auth:api')->get('/user',function(Request $request){return $request->user();});Route::resource('products',ProductController::class);Route::resource('categories',CategoryController::class);
En el método test_update_product del ProductControllerTest me salía el siguiente error:
"1) Tests\Feature\ProductControllerTest::test_update_product
Header [content-type] was found, but value [text/html; charset=UTF-8] does not match [application/json].
Failed asserting that two strings are equal."
Se soluciona agregando los headers directamente en la función de jsonPatch y no en una línea extra como en el ejemplo:
-------------------------------------------- ANTES -----------------------------------------------------
$response = $this->patchJson("/api/products/{$product->getKey()}", $data);
$response->assertHeader('content-type', 'application/json');
$response->assertSuccessful();
------------------------------------------- DESPUÉS ----------------------------------------------------
$response = $this->patchJson("/api/products/{$product->getKey()}", $data, ['content-type', 'application/json']);
$response->assertSuccessful();
Muchas gracias por el aporte!!!!
Aqui la clase para hacer el test con los metodos, me tome la libertad de hacer algunos ligeros cambios para hacer mas comodo el test y en algunos metodo solo cambie la forma de traer el response para fines ilustrativos:
muchas gracias, definitivamente me habia dado cuenta cuando creo los datos falsos en el factory que la sintaxis es distinta a laravel 8.
Si alguien tiene problemas con los tests una manera sencilla de debuggear es implementando el metodo getContent:
dd(json_decode($response->getContent()));
Con esto pueden obtener la salida de su response, si alguien no tiene configurado PHPStorm puede usar tambien el comando:
php artisan test
Si alguien no tiene PHPStorm como editor puede probarlo gratis por 30 dias o si tiene un correo educativo solicitar la licencia para estudiante, si quieren saber mas de esta herramienta tambien les recomiendo en youtube la playlist de PHPStorm de Christopher Rumpel.
Tengo una consulta, es posible poder configurar sqlite para realizar los test y tener otra base de dato(mysql o postgres) para el sistema??
en el archivo phpunit.xml toma por defecto el archivo database/database.sqlite, lo que normalmente se usa para los test.
No me gusta que el curso sea en laravel 7, ahorita lo estoy haciendo y me da error al crear el proyecto en dicha version, ademas en laravel 8 donde lo estoy haciendo da errores...
Actualicen si son tan amables..
Todo mal!!!!, Les recomiendo que tomen otro curso, por que el que lo dicta, no explica casi nada (bueno se sabe que este curso es 'avanzando', pero aun asi debe tomar detalle en algunos temas y explicarlo), solo copia y pega desde otro proyecto, perdida de tiempo con este curso.
Totalmente de acuerdo
No supe como ejecutar los test con el debugger de Visual Studio Code y busque otra manera, si tienes el mismo problema que yo puedes utilizar el comando "php vendor/phpunit/phpunit/phpunit --filter test_update_product ProductController tests\Feature\ProductControllerTest.php" para ejecutar cada uno de los test en Windows:
php vendor/phpunit/phpunit/phpunit/ para ejectura todos los test.
Puedes especificar la clase y que método en especifico quieres ejecutar con la etiqueta --filter <método_de_la_clase> <dirección_del_<archivo>.
Si les ocurre un error en el test en el apartado "update" es porque faltó el return