Implementación de Endpoints para Listar y Mostrar Posts con TDD

Clase 11 de 33Curso de Creación de APIs con Ruby on Rails

Resumen

El enfoque correcto con TDD en Rails te permite construir endpoints confiables desde el primer día. Aquí verás cómo diseñar pruebas con RSpec y generar datos con FactoryBot y Faker para los GET /posts y GET /posts/:id, validando el payload, el estado 200 y el comportamiento con y sin datos. La clave: escribir primero las pruebas, provocar los fallos esperados y luego implementar.

¿Cómo aplicar TDD para los endpoints de posts en Rails?

Es vital partir desde la carpeta spec y crear un nuevo spec para posts. Se plantean dos rutas: listar con GET /posts y mostrar con GET /posts/:id. Primero se copian y adaptan estructuras previas, luego se define qué debe ocurrir en cada caso: cuando no hay datos la lista debe estar vacía y el estado debe ser 200. Con datos insertados, el payload debe igualar en tamaño a lo creado y también responder 200.

¿Qué pruebas cubren listar y mostrar posts?

  • Listar sin datos: lista vacía y estado 200.
  • Listar con datos: tamaño del payload igual a los posts creados y estado 200.
  • Mostrar detalle: payload no vacío, estado 200 y el ID del payload igual al del post creado.

Ejemplo de estructura en RSpec para index y show:

# spec/requests/posts_spec.rb
require 'rails_helper'

RSpec.describe 'Posts', type: :request do
  describe 'GET /posts' do
    context 'sin datos en la base de datos' do
      it 'retorna lista vacía y 200' do
        get '/posts'
        expect(response.status).to eq(200)
        expect(JSON.parse(response.body)).to be_empty
      end
    end

    context 'con datos en la base de datos' do
      let(:posts) { FactoryBot.create_list(:post, 10, published: true) }

      it 'retorna todos los posts publicados y 200' do
        posts
        get '/posts'
        payload = JSON.parse(response.body)
        expect(response.status).to eq(200)
        expect(payload.size).to eq(posts.size)
      end
    end
  end

  describe 'GET /posts/:id' do
    it 'retorna un post y 200' do
      post = FactoryBot.create(:post)
      get "/posts/#{post.id}"
      payload = JSON.parse(response.body)
      expect(response.status).to eq(200)
      expect(payload['id']).to eq(post.id)
    end
  end
end

¿Cómo estructurar RSpec con describe, context y let?

  • Usa describe para agrupar por ruta o acción.
  • Separa escenarios con context: "con datos" y "sin datos".
  • Declara datos con let para crear listas con FactoryBot. Esto los hace reutilizables dentro de cada prueba.

¿Cómo generar datos de prueba con FactoryBot y Faker?

Primero, genera los factories con el generador de Rails: rails g factory bot model user email:string name:string auth_token:string y luego para post con title:string content:string published:boolean user:references. Después, ajusta los valores por defecto usando Faker para que los datos sean válidos y realistas.

¿Cómo crear factories para user y post?

# spec/factories/users.rb
FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    name  { Faker::Name.name }
    auth_token { 'my_string' }
  end
end
# spec/factories/posts.rb
FactoryBot.define do
  factory :post do
    title     { Faker::Lorem.sentence }
    content   { Faker::Lorem.paragraph }
    published {
      r = rand(0..1)
      r == 0 ? false : true
    }
    user
  end
end

Puntos clave al crear factories: - Usa Faker para emails, nombres, títulos y párrafos. - Define published como booleano real, no nulo. - Declara la asociación con user para que se cree automáticamente.

¿Cómo usar datos aleatorios y asociaciones?

  • Datos aleatorios ayudan a detectar fallos por validaciones reales.
  • La asociación user en el factory de post evita tener que crear usuarios manualmente en cada prueba.

¿Cómo validar booleanos y solucionar errores comunes?

Al ejecutar las pruebas y la consola en el entorno de pruebas con la variable de entorno de Rails, se detectó un error típico: el validador de presencia marca false como vacío en atributos booleanos. Por eso, aunque published estaba en false, se consideraba inválido.

¿Por qué presence falla con booleanos?

  • El validador de presence trata false como valor vacío.
  • Con booleanos, false puede ser un estado válido y debe aceptarse.

¿Qué cambio hacer con inclusion para published?

Reemplaza la presencia por inclusión explícita en booleanos:

# app/models/post.rb
class Post < ApplicationRecord
  validates :published, inclusion: { in: [true, false] }
end

Además, ajusta la prueba del modelo para no requerir presencia en published. Tras este cambio, las fallas se reducen a lo esperado por TDD: rutas inexistentes aún por implementar en el controlador.

¿Quieres que revisemos la implementación del controlador y las rutas para que las pruebas pasen? Deja tus preguntas y comenta qué parte te interesa profundizar.

      Implementación de Endpoints para Listar y Mostrar Posts con TDD