Pregunta ¿Cuál es la diferencia entre "include_examples" y "it_behaves_like"?


En RSpec, ¿cuál es la diferencia entre it_behaves_like y include_examples?

los documentación dice:

include_examples - incluir (s) los ejemplos en el contexto actual

it_behaves_like "name" - incluir (s) los ejemplos en un contexto anidado

Pero, ¿qué significa esto realmente? Reemplazar uno con el otro no parece tener un efecto sobre si mis pruebas pasan o no. ¿Hay alguna razón para preferir uno sobre otro en algunas situaciones?

Además, son it_should_behave_like y it_behaves_like solo sinónimos?


32
2017-10-24 03:18


origen


Respuestas:


Usted probablemente sabe cómo usar describe, context, it y specify para comunicar claramente un aspecto de tu código. El contexto anidado proporcionado por it_behaves_like se puede utilizar para mejorar esta comunicación con el lector.

Basaré mi ejemplo en el ejemplo dado en la documentación de RSpec para ejemplos compartidos:

shared_examples "a collection" do
  context "initialized with 3 items" do
    it "says it has three items" do
      # ...
    end
  end
end

describe Array do
  it_behaves_like "a collection"
  include_examples "a collection"
end

Si ejecuta RSpec con --format documentation obtienes el siguiente resultado:

Array
  behaves like a collection
    initialized with 3 items
      says it has three items
  initialized with 3 items
    says it has three items

Entonces, la diferencia es cómo se lee la especificación, por ejemplo, en caso de falla.

El estilo que prefiera es una cuestión de estética de cómo le gustan sus especificaciones para leer. Además, sugeriría usar siempre el mismo estilo si trabaja en equipo para mejorar la coherencia.


Además, ¿es it_should_behave_like y it_behaves_like solo sinónimos?

Casi, el contexto se nombra de manera diferente. it should behave like ... vs behaves like .... Nuevamente una cuestión de estética.


30
2017-10-24 04:52



Ahí es una diferencia en caso de que pase parámetros a los shared_examples.

Se explica muy bien en una advertencia en su documento:

ADVERTENCIA: cuando incluye ejemplos parametrizados en el contexto actual múltiples   veces, puede anular las definiciones de métodos anteriores y gana la última declaración.   Entonces, si tienes este tipo de ejemplo compartido (o contexto compartido)

RSpec.shared_examples "some example" do |parameter|
  \# Same behavior is triggered also with either `def something; 'some value'; end`
  \# or `define_method(:something) { 'some value' }`
  let(:something) { parameter }
  it "uses the given parameter" do
    expect(something).to eq(parameter)
  end
end

RSpec.describe SomeClass do
  include_examples "some example", "parameter1"
  include_examples "some example", "parameter2"
end

En realidad estás haciendo esto (fíjate que el primer ejemplo fallará):

RSpec.describe SomeClass do
  \# Reordered code for better understanding of what is happening
  let(:something) { "parameter1" }
  let(:something) { "parameter2" }

  it "uses the given parameter" do
    \# This example will fail because last let "wins"
    expect(something).to eq("parameter1")
  end

  it "uses the given parameter" do
    expect(something).to eq("parameter2")
  end
end

Para evitar este tipo de error sutil, se emite una advertencia si   declara múltiples métodos con el mismo nombre en el mismo contexto.   Si recibes esta advertencia, la solución más simple es reemplazar   include_examples with it_behaves_like, de esta manera el método reemplaza   se evita debido al contexto anidado creado por it_behaves_like


13
2017-07-25 20:40