← Ruby EspañolChapter 12 of 13

Pruebas con RSpec

## Objetivos de Aprendizaje - Comprender los fundamentos de pruebas - Escribir pruebas RSpec - Usar matchers efectivamente - Organizar pruebas con describe y context ## Fundamentos de Pruebas ### Por que Probar? - Detectar bugs tempranamente - Prevenir regresiones - Documentar comportamiento - Habilitar refactorizacion con confianza ### Tipos de Pruebas | Tipo | Descripcion | |------|-------------| | Unitaria | Probar metodos individuales | | Integracion | Probar interacciones entre componentes | | Funcional | Probar caracteristicas de extremo a extremo | | Rendimiento | Probar velocidad y escalabilidad | ## Vision General de RSpec RSpec es el framework BDD de pruebas mas popular de Ruby. ### Instalacion ```ruby # Gemfile group :test do gem 'rspec' end ``` ```bash bundle install rspec --init ``` ## Estructura Basica ### Archivo Spec ```ruby # spec/calculadora_spec.rb RSpec.describe Calculadora do describe '#sumar' do it 'retorna la suma de dos numeros' do calc = Calculadora.new expect(calc.sumar(2, 3)).to eq(5) end end end ``` ### Ejecutar Pruebas ```bash rspec rspec spec/calculadora_spec.rb rspec spec/calculadora_spec.rb:10 # Ejecutar prueba especifica ``` ## Describe y Context ```ruby RSpec.describe Pedido do describe '#total' do context 'cuando el pedido esta vacio' do it 'retorna cero' do pedido = Pedido.new expect(pedido.total).to eq(0) end end context 'cuando el pedido tiene articulos' do it 'retorna la suma de precios' do pedido = Pedido.new pedido.agregar_articulo(Articulo.new(precio: 10)) pedido.agregar_articulo(Articulo.new(precio: 20)) expect(pedido.total).to eq(30) end end end end ``` ## Matchers ### Igualdad ```ruby expect(actual).to eq(esperado) # Valor igual expect(actual).to eql(esperado) # Valor igual (menos estricto) expect(actual).to be(esperado) # Mismo objeto expect(actual).to equal(esperado) # Mismo objeto (identidad) ``` ### Veracidad ```ruby expect(actual).to be_truthy expect(actual).to be_falsey expect(actual).to be_nil expect(actual).to be true expect(actual).to be false ``` ### Comparaciones ```ruby expect(actual).to be > valor expect(actual).to be >= valor expect(actual).to be < valor expect(actual).to be <= valor expect(actual).to be_between(min, max) expect(actual).to match(/patron/) ``` ### Colecciones ```ruby expect(actual).to include(elemento) expect(actual).to contain_exactly(elemento1, elemento2) expect(actual).to start_with(item) expect(actual).to end_with(item) expect(actual).to have_attributes(clave: valor) ``` ### Tipos ```ruby expect(actual).to be_a(Clase) expect(actual).to be_an_instance_of(Clase) expect(actual).to respond_to(:nombre_metodo) ``` ### Errores ```ruby expect { codigo }.to raise_error expect { codigo }.to raise_error(ClaseDeError) expect { codigo }.to raise_error('mensaje') expect { codigo }.to raise_error(ClaseDeError, 'mensaje') ``` ### Predicados ```ruby expect(actual).to be_empty expect(actual).to be_valid expect(array).to be_an(Array) ``` ## Hooks Before y After ```ruby RSpec.describe Usuario do before(:each) do @usuario = Usuario.create(nombre: 'Alicia') end after(:each) do Usuario.destroy_all end before(:all) do @admin = Usuario.create(nombre: 'Admin', rol: 'admin') end after(:all) do Usuario.destroy_all end # O con :context para configuracion por contexto before(:context) do # Se ejecuta una vez antes de todos los ejemplos en este grupo end end ``` ## Let y Let ```ruby RSpec.describe Usuario do # lazy evaluation (solo creado cuando se usa) let(:usuario) { Usuario.create(nombre: 'Alicia') } # eager evaluation (creado antes de cada ejemplo) let!(:post) { Post.create(titulo: 'Prueba', autor: 'Alicia') } it 'tiene posts' do expect(usuario.posts).to include(post) end end ``` ## Ejemplos Compartidos ```ruby RSpec.shared_examples 'una cosa contable' do it 'comienza en cero' do expect(subject.count).to eq(0) end it 'incrementa el conteo' do subject.increment expect(subject.count).to eq(1) end end RSpec.describe Contador do it_behaves_like 'una cosa contable' end RSpec.describe Lista do it_behaves_like 'una cosa contable' end ``` ## Focus y Skip ```ruby # Focus - ejecutar solo esta prueba it 'esta prueba', focus: true do expect(true).to be true end # Skip - no ejecutar esta prueba it 'no se ejecutara', skip: true do expect(true).to be false end # Pending - se ejecuta pero no falla it 'esta pendiente' do skip 'razon' end ``` ## Test Doubles ### Dummy ```ruby let(:dummy) { Object.new } ``` ### Fake ```ruby fake_usuario_repo = FakeUsuarioRepositorio.new ``` ### Stub ```ruby allow(Object).to receive(:metodo).and_return(valor) allow(Object).to receive_messages(metodo1: valor1, metodo2: valor2) ``` ### Mock ```ruby expect(Object).to receive(:metodo).with(args).and_return(valor) expect(Object).to receive(:metodo).exactly(3).times expect(Object).to receive(:metodo).at_least(:once) ``` ### Spy ```ruby Object spy: Object.new allow(Object).to receive(:metodo) Object.metodo expect(Object).to have_received(:metodo) ``` ## Feature Specs (Capybara) ```ruby require 'capybara/rspec' RSpec.describe 'Registro de usuario' do scenario 'usuario se registra exitosamente' do visit '/usuarios/nuevo' fill_in 'Nombre', with: 'Alicia' fill_in 'Email', with: 'alice@ejemplo.com' click_button 'Registrarse' expect(page).to have_content('Bienvenida, Alicia!') end end ``` ## Organizacion de Pruebas ```text spec/ ├── spec_helper.rb # Configuracion compartida ├── support/ # Modulos de ayuda │ └── factories.rb ├── models/ │ ├── usuario_spec.rb │ └── post_spec.rb └── features/ └── registro_usuario_spec.rb ``` ### spec_helper.rb ```ruby RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end config.shared_context_metadata_behavior = :apply_to_host_groups config.filter_run_when_matching :focus config.example_status_persistence_file_path = 'spec/examples.txt' config.disable_monkey_patching! config.order = :random Kernel.srand config.seed end ``` ## Resumen - RSpec usa `describe` y `context` para agrupar pruebas - `it` define un caso de prueba - Matchers: `eq`, `be`, `include`, `match`, `raise_error`, etc. - Hooks `before`/`after` para configuracion/desmontaje - `let` y `let!` para datos de prueba - Test doubles: dummy, fake, stub, mock, spy - Ejemplos compartidos para logica de prueba reutilizable - `rspec --init` para inicializar RSpec

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →