unit-testing - unitarias - unit test project c#
Prueba unitaria nombrando las mejores prácticas (12)
Consulte: http://googletesting.blogspot.com/2007/02/tott-naming-unit-tests-responsibly.html
Para los nombres de los métodos de prueba, personalmente me parece muy útil usar nombres verbales y auto documentados (junto con los comentarios de Javadoc que explican con más detalle lo que está haciendo la prueba).
¿Cuáles son las mejores prácticas para nombrar las clases de prueba de unidad y los métodos de prueba?
Esto se discutió en SO antes, en ¿Cuáles son algunas convenciones de denominación populares para las Pruebas de unidad?
No sé si este es un enfoque muy bueno, pero actualmente en mis proyectos de prueba, tengo asignaciones uno a uno entre cada clase de producción y una clase de prueba, por ejemplo, Product
y ProductTest
Product
.
En mis clases de prueba, tengo métodos con los nombres de los métodos que estoy probando, un guión bajo y luego la situación y lo que espero que suceda, por ejemplo, Save_ShouldThrowExceptionWithNullName()
.
Creo que una de las cosas más importantes es ser coherente en su convención de nombres (y acordarlo con otros miembros de su equipo). Muchas veces veo un montón de diferentes convenciones utilizadas en el mismo proyecto.
Debo agregar que mantener sus pruebas en el mismo paquete pero en un directorio paralelo a la fuente que se está probando elimina la acumulación de código una vez que esté listo para implementarlo sin tener que hacer un montón de patrones de exclusión.
Personalmente, me gustan las mejores prácticas descritas en "JUnit Pocket Guide" ... ¡es difícil superar un libro escrito por el coautor de JUnit!
El nombre del caso de prueba para la clase Foo debe ser FooTestCase o algo parecido (FooIntegrationTestCase o FooAcceptanceTestCase) - ya que es un caso de prueba. visite http://xunitpatterns.com/ para conocer algunas convenciones de nomenclatura estándar como prueba, caso de prueba, dispositivo de prueba, método de prueba, etc.
En VS + NUnit, normalmente creo carpetas en mi proyecto para agrupar las pruebas funcionales. Luego creo clases de aparatos de prueba de unidad y las nombro según el tipo de funcionalidad que estoy probando. Los métodos de [Prueba] se nombran a lo largo de las líneas de Can_add_user_to_domain
:
- MyUnitTestProject
+ FTPServerTests <- Folder
+ UserManagerTests <- Test Fixture Class
- Can_add_user_to_domain <- Test methods
- Can_delete_user_from_domain
- Can_reset_password
Me gusta la estrategia de nombramiento de Roy Osherove , es la siguiente:
[UnitOfWork_StateUnderTest_ExpectedBehavior]
Tiene toda la información necesaria sobre el nombre del método y de manera estructurada.
La unidad de trabajo puede ser tan pequeña como un solo método, una clase o tan grande como varias clases. Debe representar todas las cosas que deben probarse en este caso de prueba y están bajo control.
Para los ensamblajes utilizo el típico final de .Tests
, que creo que está bastante extendido y lo mismo para las clases (que terminan con los Tests
):
[NameOfTheClassUnderTestTests Test]
Anteriormente usé Fixture como sufijo en lugar de Pruebas, pero creo que esta última es más común, luego cambié la estrategia de nomenclatura.
Me gusta este estilo de nombre:
OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();
y así. Deja realmente claro a un no probador cuál es el problema.
Me gusta seguir el estándar de denominación "Debería" para las pruebas al nombrar el dispositivo de prueba después de la unidad bajo prueba (es decir, la clase).
Para ilustrar (usando C # y NUnit):
[TestFixture]
public class BankAccountTests
{
[Test]
public void Should_Increase_Balance_When_Deposit_Is_Made()
{
var bankAccount = new BankAccount();
bankAccount.Deposit(100);
Assert.That(bankAccount.Balance, Is.EqualTo(100));
}
}
¿Por qué "debería" ?
Encuentro que obliga a los escritores de prueba a nombrar la prueba con una oración como "Debería [estar en algún estado] [después / antes / cuando] [la acción tiene lugar]"
Sí, escribir "Debería" en todas partes se vuelve un poco repetitivo, pero como dije, obliga a los escritores a pensar de la manera correcta (así puede ser bueno para los principiantes). Además, generalmente da como resultado un nombre de prueba en inglés legible.
Actualización :
Me he dado cuenta de que Jimmy Bogard también es fanático de ''debería'' e incluso tiene una biblioteca de pruebas de unidad llamada Should .
Actualización (4 años después ...)
Para aquellos interesados, mi enfoque para nombrar las pruebas ha evolucionado a lo largo de los años. Uno de los problemas con el patrón de Debo que describo anteriormente es que no es fácil saber de un vistazo qué método está bajo prueba. Para la POO, creo que tiene más sentido comenzar el nombre de la prueba con el método bajo prueba. Para una clase bien diseñada, esto debería resultar en nombres de métodos de prueba legibles. Ahora uso un formato similar al <method>_Should<expected>_When<condition>
. Obviamente, dependiendo del contexto, es posible que desee sustituir los verbos Should / When por algo más apropiado. Ejemplo: Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()
Recientemente se me ocurrió la siguiente convención para nombrar mis pruebas, sus clases y proyectos que contienen para maximizar sus descriptivenes:
Digamos que estoy probando la clase de configuración en un proyecto en el espacio de nombres de MyApp.Serialization .
Primero, crearé un proyecto de prueba con el espacio de nombres MyApp.Serialization.Tests .
Dentro de este proyecto y, por supuesto, el espacio de nombres crearé una clase llamada IfSettings (guardada como IfSettings.cs).
Digamos que estoy probando el método SaveStrings () . -> Nombraré la prueba CanSaveStrings () .
Cuando ejecute esta prueba se mostrará el siguiente encabezado:
MyApp.Serialization.Tests.IfSettings.CanSaveStrings
Creo que esto me dice muy bien lo que está probando.
Por supuesto, es útil que en inglés el sustantivo "Pruebas" sea el mismo que el verbo "pruebas".
No hay límite para su creatividad al nombrar las pruebas, de modo que obtenemos encabezados completos de las oraciones para ellas.
Normalmente, los nombres de prueba tendrán que comenzar con un verbo.
Ejemplos incluyen:
- Detecta (por ejemplo, DetectsInvalidUserInput)
- Tiros (por ejemplo, tiros en nudos)
- Will (por ejemplo, WillCloseTheDatabaseAfterTheTransaction)
etc.
Otra opción es usar "that" en lugar de "if".
Sin embargo, este último me ahorra pulsaciones y describe más exactamente lo que estoy haciendo, ya que no sé, que el comportamiento probado está presente, pero estoy probando si lo está.
[ Editar ]
Después de usar la convención de nomenclatura anterior por un poco más de tiempo, he descubierto que el prefijo If puede ser confuso al trabajar con interfaces. Da la casualidad de que la clase de prueba IfSerializer.cs parece muy similar a la interfaz ISerializer.cs en la pestaña "Abrir archivos". Esto puede ser muy molesto al alternar entre las pruebas, la clase que se está probando y su interfaz. Como resultado, ahora elegiría Eso sobre si como prefijo.
Además, ahora uso, solo para los métodos en mis clases de prueba, ya que no se considera la mejor práctica en ninguna otra parte, el "_" para separar las palabras en los nombres de mis métodos de prueba como en:
- [Prueba] public void detects_invalid_User_Input () *
Me parece que esto es más fácil de leer.
[ Fin Editar ]
Espero que esto genere más ideas, ya que considero que las pruebas de nomenclatura son de gran importancia, ya que pueden ahorrarle mucho tiempo que, de lo contrario, se habría dedicado a tratar de entender lo que están haciendo las pruebas (p. Ej., Después de reanudar un proyecto después de una pausa prolongada) .
Uso el concepto de Given-When-Then . Echa un vistazo a este breve artículo http://cakebaker.42dh.com/2009/05/28/given-when-then/ . El artículo describe este concepto en términos de BDD, pero también puede utilizarlo en TDD sin ningún cambio.
Kent Beck sugiere:
Un dispositivo de prueba por ''unidad'' (clase de su programa). Los accesorios de prueba son clases en sí mismas. El nombre del dispositivo de prueba debe ser:
[name of your ''unit'']Tests
Los casos de prueba (los métodos del dispositivo de prueba) tienen nombres como:
test[feature being tested]
Por ejemplo, tener la siguiente clase:
class Person {
int calculateAge() { ... }
// other methods and properties
}
Un accesorio de prueba sería:
class PersonTests {
testAgeCalculationWithNoBirthDate() { ... }
// or
testCalculateAge() { ... }
}
Nombres de clase . Para los nombres de los dispositivos de prueba, encuentro que "Prueba" es bastante común en el lenguaje ubicuo de muchos dominios. Por ejemplo, en un dominio de ingeniería: StressTest
, y en un dominio de cosméticos: SkinTest
. Lamento no estar de acuerdo con Kent, pero usar "Prueba" en mis pruebas ( StressTestTest
?) Es confuso.
"Unidad" también se usa mucho en los dominios. Ej. MeasurementUnit
. ¿Una clase llamada MeasurementUnitTest
una prueba de "Measurement" o "MeasurementUnit"?
Por lo tanto, me gusta usar el prefijo "Qa" para todas mis clases de prueba. Por ejemplo, QaSkinTest
y QaMeasurementUnit
. Nunca se confunde con los objetos de dominio, y usar un prefijo en lugar de un sufijo significa que todos los dispositivos de prueba viven juntos visualmente (útil si tiene falsificaciones u otras clases de soporte en su proyecto de prueba)
Espacios de nombres . Trabajo en C # y mantengo mis clases de prueba en el mismo espacio de nombres que la clase que están probando. Es más conveniente que tener espacios de nombres de prueba separados. Por supuesto, las clases de prueba están en un proyecto diferente.
Métodos de prueba de nombres . Me gusta nombrar mis métodos WhenXXX_ExpectYYY. Aclara la condición previa y ayuda con la documentación automatizada (a la TestDox). Esto es similar al asesoramiento en el blog de pruebas de Google, pero con una mayor separación de condiciones previas y expectativas. Por ejemplo:
WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory