2010-02-01 5 views
8

Utilizando un pequeño proyecto de C (actualmente a 150 loc, probablemente menos de 500 cuando termine) en el que estoy trabajando, me estoy enseñando a mí mismo el desarrollo impulsado por pruebas. De acuerdo con algunas cosas que he encontrado en la web, especialmente these slides by Olve Maudal, acabo de utilizar afirmaciones en mis pruebas unitarias.¿Cuándo usar un marco de prueba de unidad (frente a usar solo aserciones)?

Como recién estoy aprendiendo tdd, hasta ahora he evitado la sobrecarga de aprender también un marco de pruebas unitarias como cunit. En este punto, mi pensamiento es que la curva de aprendizaje adicional, aunque superficial, de un marco no vale la pena el esfuerzo para un proyecto tan pequeño. Me pregunto: ¿esto es incorrecto (es decir, estaría mejor aprendiendo el marco ahora)? ¿En qué punto el aprendizaje de un marco vale la pena?

Respuesta

6

El punto de equilibrio para el aprendizaje de un marco de prueba de unidad no es largo para llegar. Dos ventajas principales que uno obtiene con un marco sobre el uso de la función assert() son

  • mensaje más detallado para el error de aserción: se espera vs. valor real
  • ejecución de todos los casos de prueba en lugar de detenerse en la primera afirmación no

Los dos dan indicios de dónde se encuentra el error.

3

Según mi experiencia con el aprendizaje de frameworks de pruebas de unidades .NET, comencé con un pequeño proyecto que luego me dio la ventaja de poder aplicar lo que había aprendido a otros proyectos más adelante, independientemente de su tamaño.

Supongo que podría estar pensando cuál es el punto, es solo un código pequeño, en este momento, pero creo que haría bien en entrar en un marco ahora más bien que tarde. Es como conducir un automóvil. Aprendí a manejar cuando tenía 17 años, aunque no obtuve mi propio automóvil hasta dos años después. Podría haber ignorado tomar lecciones hasta que obtuve mi auto, pero pasé y ya tenía las habilidades para seguir y conducir.

Es una analogía extraña, pero así es como pienso cuando se trata de aprender algo así como un marco o una biblioteca: nunca se sabe lo que le resultará útil.

1

Conozca un marco xUnit: cuando ingrese a la programación de proyectos comerciales a gran escala, descubrirá que se utilizan ampliamente.

+0

Gracias por la respuesta. La mayor parte de mi trabajo se realiza en entornos científicos y tiende a proyectos relativamente pequeños. Sin embargo, me estoy inclinando por un marco de trabajo de xunit, especialmente porque es probable que use otros cuando cambio de idioma. – GreenMatt

1

Desde que estoy aprendiendo tdd, hasta ahora he evitado la sobrecarga de aprender también un marco de pruebas de unidades como cunit. En este punto, mi pensamiento es que la curva de aprendizaje adicional, aunque superficial, de un marco no vale la pena el esfuerzo para un proyecto tan pequeño. Me pregunto: ¿esto es incorrecto (es decir, estaría mejor aprendiendo el marco ahora)? ¿En qué punto el aprendizaje de un marco vale la pena?

Estoy de acuerdo con Philippe, Jason y Paolo, pero quería lanzar en otra forma de verlo:

Los llamados xUnit marcos son una muy simple y ligero, tanto como biblioteca para descargar (los binarios de, por ejemplo, la última JUnit o CUnit son alrededor de 200 kilobytes) y, más importante, conceptualmente.

Si estás haciendo (o le gustaría hacer) cualquier prueba unidad en absoluto, que sin duda beneficiarse del uso de una herramienta probada, y aprender xUnit comenzará a pagar de inmediato.Creo que es posible que hayas sobreestimado un poco la "sobrecarga", no dejes que la palabra "framework" te asuste ;-) - estarás funcionando con xUnit en media hora o menos.

Descargo de responsabilidad: Su pregunta no está etiquetada C, entonces la tomé como una agnóstica. No sé si las pruebas unitarias son muy diferentes en el lado C (en comparación con Java), pero lo dudo. :-)

0

Una nota: si está siguiendo el patrón normal de rojo-verde-refactor, entonces a medida que refactoriza sus pruebas unitarias, el código resultante debería evolucionar hacia un marco de prueba unitario. Por ejemplo, usted no debe tener dos copias del código que hace

if (expected != actual) {printf("%d != %d", actual, expected); return -1;} 

Eso debería ser rediseñado en algo así como

void AssertNotEqual(int expected, int actual, char* message) 
{ 
    if (expected != actual) {printf(message, actual, expected); return -1;} 
} 
1

continuación se presenta un ejemplo de C# .Net donde un Moq framework es útil en un MSTest usando Visual Studio.

Observe la diferencia entre TestOld() y MoqTest(). El propósito de ambas pruebas es el mismo. Pero en TestOld(), necesito escribir MyMemberManagerForTest implementación concreta. Mientras que en MoqTest(), el framework Moq me hará la tarea.

_mockIMemberManager = new Mock<IMemberManager>(); 
    _mockIMemberManager.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member); 

Referencia: How to Use Mock Library For Your Unit Testing In C#

[TestClass()] 
public class TestMembershipManager 
{ 
    private LibraryCore _targetLibraryCore; 

    #region Old Test withou Moq 

    public class MyMemberManagerForTest : IMemberManager 
    { 
     public Member GetMember(int memberID) 
     { 
      Member member = new Member() 
      { 
       MemberID = 1, 
       FirstName = "Lijo", 
       MaximumBookCanBorrow = 4, 
      }; 

      return member; 
     } 
    } 

    private IMemberManager _memberManager; 

    [TestMethod()] 
    public void TestOld() 
    { 
     _memberManager = new MyMemberManagerForTest(); 
     _targetLibraryCore = new LibraryCore(_memberManager); 

     int memberID = 1; 
     double expected = 12; 
     double actual; 

     //TEST 
     actual = _targetLibraryCore.CalculateMembershipCost(memberID); 
     Assert.AreEqual(expected, actual); 
    } 


    #endregion 

    #region Test with Moq 
    private Mock<IMemberManager> _mockIMemberManager; 

    [TestMethod()] 
    public void MoqTest() 
    { 
     _mockIMemberManager = new Mock<IMemberManager>(); 
     _targetLibraryCore = new LibraryCore(_mockIMemberManager.Object); 

     Member member = new Member() 
     { 
      MemberID = 1, 
      FirstName = "Lijo", 
      MaximumBookCanBorrow = 4, 
     }; 

     _mockIMemberManager.Setup(x => x.GetMember(It.IsAny<int>())).Returns(member); 

     int memberID = 1; 
     double expected = 12; 
     double actual; 

     //TEST 
     actual = _targetLibraryCore.CalculateMembershipCost(memberID); 
     Assert.AreEqual(expected, actual); 
    } 

    #endregion 

} 

Para este tipo de pruebas para trabajar, es importante que el código para utilizar Dependency Injection como se puede ver en el constructor LibraryCore sobrecargado

public class LibraryCore 
{ 
    private readonly IMemberManager _memberManager; 

    public LibraryCore(IMemberManager memberManager) 
    { 
     this._memberManager = memberManager; 
    } 

    public double CalculateMembershipCost(int memberID) 
    { 
     double membershipCost = 0; 
     Member member = _memberManager.GetMember(memberID); 
     membershipCost = 10 + member.MaximumBookCanBorrow * 0.5; 
     return membershipCost; 
    } 
} 
Cuestiones relacionadas