No especificó un idioma, así que trataré de mantener esto un tanto genérico. Sin embargo, será difícil, ya que es mucho más fácil expresar conceptos con código real.
Las pruebas unitarias pueden ser un poco confusas al principio. A veces no siempre está claro cómo probar algo, o cuál es el propósito de una prueba.
Me gusta tratar las pruebas unitarias como una forma de probar pequeñas piezas individuales de código.
El primer lugar que utilizo pruebas unitarias es para verificar que algún método funcione como lo espero para todos los casos. Recientemente escribí un método de validación para un número de teléfono para mi sitio. Acepto cualquier entrada, desde 123-555-1212, (123) 555-1212, etc. Quiero asegurarme de que mi método de validación funcione para todos los formatos posibles. Sin una prueba unitaria, me vería obligado a ingresar manualmente cada formato diferente, y verificar que el formulario se publique correctamente. Esto es muy tedioso y propenso a errores. Más adelante, si alguien realiza un cambio en el código de validación del teléfono, sería bueno si pudiéramos verificarlo fácilmente para asegurarnos de que nada más se rompió. (Tal vez agregamos soporte para el código de país). Por lo tanto, aquí hay un ejemplo trivial:
public class PhoneValidator
{
public bool IsValid(string phone)
{
return UseSomeRegExToTestPhone(phone);
}
}
podría escribir una prueba unitaria de esta manera:
public void TestPhoneValidator()
{
string goodPhone = "(123) 555-1212";
string badPhone = "555 12"
PhoneValidator validator = new PhoneValidator();
Assert.IsTrue(validator.IsValid(goodPhone));
Assert.IsFalse(validator.IsValid(badPhone));
}
Esos 2 líneas Assert verificarán que el valor devuelto por IsValid() es verdadero y falso, respectivamente.
En el mundo real, es probable que tenga muchos ejemplos de números de teléfono buenos y malos. Tengo alrededor de 30 números de teléfono contra los que pruebo. Simplemente ejecutando esta prueba unitaria en el futuro le dirá si la lógica de validación de su teléfono está rota.
También podemos usar pruebas unitarias para simular cosas fuera de nuestro control.
Las pruebas unitarias deben ejecutarse independientemente de los recursos externos. Sus pruebas no deben depender de una base de datos presente o de un servicio web disponible. Entonces, en cambio, simulamos estos recursos, para que podamos controlar lo que devuelven. En mi aplicación, por ejemplo, no puedo simular una tarjeta de crédito rechazada en el registro. Al banco probablemente no le gustaría que envíe miles de tarjetas de crédito malas solo para asegurarse de que mi código de manejo de errores sea correcto. Aquí hay un código de muestra:
public class AccountServices
{
private IBankWebService _webService = new BankWebService();
public string RegisterUser(string username, string creditCard)
{
AddUserToDatabase(username);
bool success = _webService.BillUser(creditCard);
if (success == false)
return "Your credit card was declined"
else
return "Success!"
}
}
Aquí es donde las pruebas unitarias son muy confusas y no obvias. ¿Qué debería hacer una prueba de este método? Lo primero, sería muy bueno si pudiéramos verificar que si la facturación fallara, se devolviera el mensaje de error apropiado. Como resultado, al usar un simulacro, hay una manera. Usamos lo que se llama Inversión de control. En este momento, AccountServices() es responsable de crear el objeto BankWebService.Dejemos que la persona que llama de esta clase los dan sin embargo:
public class AccountServices
{
public AccountServices(IBankWebService webService)
{
_webService = webService;
}
private IBankWebService _webService;
public string RegisterUser(string username, string creditCard)
{
AddUserToDatabase(username);
bool success = _webService.BillUser(creditCard);
if (success == false)
return "Your credit card was declined"
else
return "Success!"
}
}
Debido a que la persona que llama es responsable de crear el objeto BankWebService, nuestra Unidad de prueba puede crear una falsa uno:
public class FakeBankWebService : IBankWebService
{
public bool BillUser(string creditCard)
{
return false; // our fake object always says billing failed
}
}
public void TestUserIsRemoved()
{
IBankWebService fakeBank = FakeBankWebService();
AccountServices services = new AccountServices(fakeBank);
string registrationResult = services.RegisterUser("test_username");
Assert.AreEqual("Your credit card was declined", registrationResult);
}
Mediante el uso de ese objeto falsa , cada vez que se llame al BillUser() de nuestro banco, nuestro objeto falso siempre devolverá falso. Nuestra prueba unitaria ahora verifica que si falla la llamada al banco, RegisterUser() devolverá el mensaje de error correcto.
Supongamos que un día se están haciendo algunos cambios, y unos pelos de punta de errores en: "éxito"
public string RegisterUser(string username, string creditCard)
{
AddUserToDatabase(username);
bool success = _webService.BillUser(creditCard);
if (success) // IT'S BACKWARDS NOW
return "Your credit card was declined"
else
return "Success!"
}
Ahora, cuando su facturación falla, método que su RegisterUser() devuelve. Afortunadamente, tiene una prueba unitaria escrita. Esa prueba unitaria ahora fallará porque ya no está regresando "Su tarjeta de crédito fue rechazada".
Es mucho más fácil y rápido encontrar el error de esta manera que llenar manualmente su formulario de registro con una tarjeta de crédito incorrecta, solo para verificar el mensaje de error.
Una vez que observa diferentes marcos de burla, hay cosas aún más poderosas que puede hacer. Puede verificar que se invocaron sus métodos falsos, puede verificar el número de veces que se invocó un método, puede verificar los parámetros con los que se invocaron los métodos, etc.
Creo que una vez que comprenda estas 2 ideas, comprenderá más que suficiente para escribir muchas pruebas unitarias para su proyecto.
Si nos dices el idioma que estás utilizando, te podemos orientar mejor.
Espero que esto ayude. Me disculpo si algo de eso es confuso. Lo limpiaré si algo no tiene sentido.
Recomiendo mirar en esta respuesta: http://stackoverflow.com/questions/18601/best-practice-for-integrating-tdd-with-web-application-development – Herter
Como hay infinitos ejemplos, esta pregunta es demasiado amplio – Raedwald