Pregunta

En primer lugar, sé que es una mala práctica tener múltiples afirmaciones en la prueba de la unidad.

Pero a veces necesitas probar alguna transacción atómica.Como ejemplo simplificado, tomemos alguna aplicación bancaria que tenga la clase de cuenta:

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.balance -= amount
    to_account.balance += amount
    Audit.create(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  end

end

En esta situación, quiero verificar 3 cosas juntas:

  1. Balance de la cuenta de origen disminuyó por amount
  2. El saldo de la cuenta de destino
  3. incrementado por amount
  4. se inserta el registro de auditoría
  5. ¿Cuál es la mejor manera de probar el método @account.transfer?

¿Fue útil?

Solución

En esta situación, quiero verificar 3 cosas juntas:

Argumentaría que lo que realmente quiere es describir el comportamiento de estas cosas bajo ciertas condiciones, y así garantizar que el comportamiento cumpla con sus especificaciones. Eso podría significar que las cosas sucedan juntas; o podría significar que algunas cosas solo ocurren en un conjunto de condiciones y no a otras personas, o que una excepción hace que todo se vuelva a rodar hasta su estado original.

No hay magia para tener todas sus afirmaciones en una prueba, excepto para hacer las cosas más rápido. A menos que se enfrente a una penalización severa de desempeño (a menudo sucede en las pruebas de pila completa), es mucho mejor usar una afirmación por prueba.

rspec lo hace directo para extraer la fase de configuración de prueba para que se repita para cada ejemplo:

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.debit!(amount)
    to_account.credit!(amount)
    Audit.create!(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  rescue SomethingBadError
    # undo all of our hard work
  end

end

describe Account do
  context "when a transfer is made to another account" do
    let(:other_account} { other_account }
    context "and the subject account has sufficient funds" do
      subject { account_with_beaucoup_bucks }
      it "debits the subject account"
      it "credits the other account"
      it "creates an Audit entry"
    end
    context "and the subject account is overdrawn" do
      subject { overdrawn_account }
      it "does not debit the subject account"
      it "does not credit the other account"
      it "creates an Audit entry" # to show the attempted transfer failed
    end
  end
end

Si las tres pruebas en el "camino feliz" pasaban, entonces todos "sucedieron juntos", ya que el estado del sistema inicial era el mismo en cada caso.

Pero también necesita asegurarse de que las cosas no suceden cuando algo sale mal y que el sistema vuelve a su estado original. Tener múltiples afirmaciones hace que sea fácil ver que esto funciona como se esperaba, y cuando las pruebas fallan, exactamente cómo Falló.

Otros consejos

Las múltiples afirmaciones por prueba no siempre son una mala práctica. Si los múltiples afirman verifican el mismo comportamiento, no hay problema con él. El problema existe al intentar verificar más de un comportamiento en la misma prueba. Por supuesto, hay algunos riesgos con múltiples afirmaciones por prueba. Uno de ellos es que accidentalmente puede dejar valores de un conjunto de prueba anterior que invalida una prueba anterior de una manera rara. Además, cuando una afirmación es falsa, no se ejecutará todo lo demás, lo que puede causar dificultades para entender lo que está pasando. Pero sea razonable, puede tener múltiples afirmaciones que afirman el mismo comportamiento, preferiblemente las cortas y sin configuración adicional.

En el caso simple que trajo, usaría múltiples afirmaciones, porque es tan simple. Pero, por supuesto, puede ser mucho más complicado, como el equilibrio negativo, los diferentes tipos de cuentas y cosas. Entonces sería mejor usar diferentes pruebas con una (preferiblemente) afirmación. Lo organizaría así:

  • 1 para probar el comportamiento de la cuenta corriente (caso más simple);
  • 1 a cada camino diferente El método puede tener (excepciones, negativas equilibrio, etc.);
  • 1 para probar la auditoría en cada una de estas posibilidades;

  • 1 para probar el comportamiento de la actualidad actual (caso más simple);

  • 1 a cada camino diferente El método puede tener. (excepciones, negativas equilibrio, etc.);
  • 1 para probar la auditoría en cada una de estas posibilidades;

Dado que la prueba de auditoría es bastante simple y no requiere una configuración adicional, también puede probarlo junto con la cuenta y la configuración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top