Pregunta

¿Está bien (conceptualmente) para ejecutar los bucles en los métodos de prueba?

Me gustaría probar una gama de valores de los parámetros en un controlador, para determinar si las diferentes entradas de retorno los valores correctos.

  test "logged in user - add something - 0 qty" do
    @app = Factory.create(:app)

    (0..5).each do |t|
      @qty = t
      login(:user)
      get :add. :id => @app.id, :qty => @qty
      assert_nil(flash[:error])
      assert_response :redirect
      assert_redirect_to :controller => :apps, :action => :show, :id => @app.id
      if @qty = 0 
        assert_equal(Invite.all.count, @qty + 1)
      else 
        assert_something .........
    end
  end

Algo por el estilo.

¿Fue útil?

Solución

Por lo general tratan de evitar cualquier tipo de sentencias condicionales o bucles en el código de prueba. Usted quiere que sus pruebas sean lo más simple posible, y si se inicia incluyendo la lógica en sus pruebas que tiene que probar a para asegurarse de que funcionan como fueron diseñados. Me gustaría romper el bucle arriba en los casos de prueba separadas, de esa manera, si alguno de ellos no es fácil de determinar exactamente qué insumos causaron el fracaso. Cuando falla una prueba que debería ser inmediatamente obvio qué lo causó. Usted no debería tener que analizar el código de prueba para averiguarlo.

Actualización:

Yo quiero añadir que hay algunos extremadamente raras los casos en que se quieren tener un bucle en los casos de prueba. Un ejemplo específico es cuando se está probando para los problemas de concurrencia. Esta es una excepción a la regla general, y usted debe tener una razón muy buena y bien entendida por tener cualquier tipo de lógica en sus pruebas.

Otros consejos

  

¿Está bien (conceptualmente) para ejecutar los bucles en los métodos de prueba?

¿Quieres decir, ¿es políticamente correcto?

Funciona, ¿verdad? Estoy tratando de imaginar lo que sería la excepción.

Las pruebas también debe ser vista como "documentación viva" de lo su software tiene que hacer, por lo que mantenerlos lo más claro posible.

No es políticamente correcto utilizar más de una afirmación o validación en cada prueba. Dicho esto, todos lo hacen. Uno de los nuevos estilos se ve en escenarios de prueba de pepino, donde el escenario está todavía en un formato muy legible, pero permite que múltiples conjuntos de datos para ser probados.

Pero de Ruby, que podría no estar usándolo si fueras el tipo de seguir la orientación de todos los demás a la carta. No hay una manera correcta, sólo el más común y que cambia muy a menudo.

Una vez le pregunté a mi dentista qué orden debo cepillar, hilo dental y enjuague. Me dijo que no le importaba si lograba realmente hacer las tres cosas. Creo que el punto es que muchas veces los de calidad inferior implementaciones son mejores que ninguno en absoluto. Si bucles que el análisis sea más divertido y por lo tanto más probable, entonces debe reproducirse el santo infierno fuera de sus pruebas.

Es aún mejor si usted puede tener su marco tenga en cuenta que ésta sola prueba es en realidad la realización de múltiples pruebas (con diferentes parámetros). Se le permite ver lo que falla exacta combinación de parámetros y que se suceden en la prueba de informe.

Puede haber casos donde se necesita bucles, pero el suyo no es necesario uno de ellos. Recuerde que la adición de más complejidad a las pruebas hace más difícil trabajar con ellos. Cuando la aplicación se desarrolla pruebas también evolucionan. Si usted los hace demasiado complejo al principio, de un día que se puede enfrentar una elección:

  • debería pasar 3 días refactorizar esta gran prueba desordenado de edad que falla?
  • debe eliminar la prueba y escribir nuevo, más simple elegante (en 3,5 días)?

Esto es difícil elección. En la primera opción que perder el tiempo para implementar nuevas características para algo que no empuja proyecto adelante? ¿Tiene tiempo para esto? ¿Su gerente piensa que tiene tiempo para esto? ¿La clienta pago de su tiempo en este proyecto cree que tiene tiempo para esto?
Segundas costuras opción de ser razonable, pero, al escribir nuevas pruebas, ¿cómo saber que todo cubierto todos los casos como una antigua (más nuevos)? Es que toda la documentación en? Es en la documentación de pruebas? ¿Recuerdas todos ellos? O tal vez usted va a través de código de prueba y refactorizar para revelar todos los casos ocultos dentro de este código burbuja? No es que esto se convierta primera opción?

No hacer pruebas como código heredado. Código nadie quiere tocar, nadie sabe en realidad, todo el mundo tratando de evitar e ignorar tanto como sea posible. Los ensayos deberán concebirse como la aplicación de descanso. Aplicar muchos principios de diseño que usted está solicitando al diseño de código. Hacerlos simple. responsabilidad separada. Agruparlos lógicamente. Que sean fáciles de refactorizar. Hacerlos extensibles. Hay muchas cosas que usted debe tener en cuenta.

En cuanto a su caso. Vamos a suponer que usted tiene de casos de uso donde el código hace algo por parámetro en <0100> (0..5 desde el código es muy juntos, miradas ejemplo más claro cuando se usa gama más amplia). En otros valores que lo hace un poco de manejo de excepciones. En este caso desea casos de prueba:

  • cuando el parámetro = -1
  • cuando el parámetro = 0
  • cuando el parámetro = 1
  • cuando el parámetro = 99
  • cuando el parámetro = 100
  • cuando el parámetro = 101

simple, casos de prueba independientes que son fáciles de refactor, fácil de leer mientras sigue comprobando código correctamente.
Se podría añadir caso de prueba en el que se utilizaría en bucle para comprobar el comportamiento cuando el parámetro es de (10,70), pero no se recomienda. Con una gran cantidad de pruebas y rangos de parámetros de ancho que se acaba de desperdicio de recursos. Si el algoritmo es determinista, hace los mismos pasos para algún conjunto de valores que va a trabajar para todos ellos si funciona para uno.
Trate de leer acerca de las clases de equivalencia, valores límite, las pruebas por parejas, cobertura de caminos, la cobertura de sentencias, cobertura de sucursales y otras técnicas de prueba para hacer mejor sus pruebas.

Me voy a añadir a mí mismo a la lista de lo políticamente incorrecto. Cuando se prueba un rango de valores, un bucle puede aumentar la legibilidad de una prueba. Además, ayuda DRY, haciendo más fácil la refactorización:? ¿Preferiría añadir el nuevo parámetro a los ocho lugares del método es llamado en la prueba, o para un solo

Esta es una prueba que utiliza esta técnica. Se trata de utilizar una biblioteca de prueba de cosecha, pero la técnica es universal:

  def test_swap_name
    test_cases = [
      [
        'Paul, Ron P.A.',
        'Ron Paul PA'
      ],
      [
        "PUBLIC, SR., JOHN Q",
        "JOHN Q PUBLIC SR"
      ],
      [
        "SMITH, JR., MARK A",
        "MARK A SMITH JR"
      ],
      [
        'James Brown',
        'James Brown'
      ],
      # (more test cases)
    ]
    for original, swapped in test_cases
      assertInfo("For original = #{original.inspect}") do
        assertEquals(original.swap_name, swapped)
      end
    end
  end

assertInfo añade una cadena arbitraria para el inicio de cualquier mensaje de excepción. Así es como se puede saber, cuando una prueba fallida, que los datos se está probando:

./StringUtil.test.rb
Method "test_swap_name" failed:
Assert::BlownAssert: For original = "Paul, Ron P.A.": Expected:
"Ron Paul PA"
but got
"Paul, Ron P.A."
./../../testlib/Assert.rb:125:in `fail_test'
./../../testlib/Assert.rb:43:in `assertEquals'
./StringUtil.test.rb:627:in `test_swap_name'

En general estoy bien con un lazo en una prueba, siempre y cuando sólo hay una ocurrencia de una afirmación en la prueba. En otras palabras, esto está bien:

test "something" do
  for item in @collection
    assert_something item
  end
end

Pero esto no es:

test "something" do
  for item in @collection
    assert_something item
    assert_something_else item
  end
end

Y estos hará que te odias:

test "something" do
  for item in @collection
    assert_something item
    if x == y
      assert_something_else item
    end
  end
end

test "something" do
  for item in @collection
    assert_something item
  end
  for item in @collection
    assert_something_else item
  end
end

Y la única vez que escribiría una prueba de esta manera es que si los elementos de la colección varían sustancialmente entre sí, pero había alguna necesidad de verificar el comportamiento comúnmente compartida. Por ejemplo, es posible que tenga diez casos de diferentes objetos, pero todos ellos se supone que responden a un cierto mensaje. Así que verifique que todas las instancias pueden hacer lo que se supone que el método de pato-mecanografiado a hacer. Pero si usted tiene una colección que siempre contiene las instancias de Foo, que a menudo mejor estás fuera sólo hacer una afirmación sobre @collection.first. Las pruebas se ejecuta más rápido, y que realmente no ganar mucho de repetir la afirmación en todos los casos, y en la mayoría de los casos, es mucho mejor haciendo una prueba item de forma aislada del resto de la colección de todos modos. Si te sientes particularmente paranoico, esto es generalmente bien:

test "items are all Foo" do
  for item in @collection
    assert_kind_of Foo, item, "Everything in @collection must be Foo."
  end
end
test "something" do
  assert_something @collection.first
end

La prueba de "algo" se producirá un error de todos modos, si tienes objetos no Foo de la colección, pero la prueba anterior deja muy claro cuál es el problema real es.

En pocas palabras, evitar, pero si usted tiene una buena razón para hacerlo, y luego seguir adelante. Y si se convierte en un problema en el futuro, la prueba todavía debe ser lo suficientemente simple que refactorización en algo menos problemático es fácil.

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