No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Pruebas Unitarias Avanzadas con XUnit en Visual Studio

8/19
Recursos

¿Cómo se crean pruebas unitarias de funciones en Visual Studio?

Las pruebas unitarias son esenciales para garantizar que el código funcione correctamente ante cambios o actualizaciones. En el contexto de Visual Studio, empleamos XUnit para implementar pruebas unitarias. Veamos un ejemplo práctico de cómo crear pruebas unitarias con XUnit utilizando la función quantityInWords.

¿Qué es la función quantityInWords y cómo la probamos?

La función quantityInWords transforma un número y una palabra en un formato legible. Por ejemplo, al introducir "car" y 7, genera "7 cars", no pluralizando la palabra y convirtiendo el número en texto.

Para probar esta función:

  1. Crear el objeto de prueba:

    Primero, debes arreglar creando el objeto que contiene la función a probar. Usamos la estructura AAA:

    var obj = new ClaseConLaFuncion(); // Reemplace con el nombre real de la clase que contiene la función
    
  2. Ejecutar la función:

    Luego, ejecuta la función deseada y almacena el resultado:

    var result = obj.QuantityInWords("car", 7);
    
  3. Verificar el resultado:

    Detallamos las validaciones con dos aserciones diferentes de XUnit:

    • StartWith: Verifica que el texto comience con el string "seven":

      Assert.StartsWith("seven", result);
      
    • Assert.Contains: Comprueba si el resultado incluye la palabra "car":

      Assert.Contains("car", result);
      

Aclaración: Si tu entorno está en español, quizá debas adaptar las palabras esperadas al idioma configurado.

¿Cómo manejar excepciones en las pruebas unitarias?

En ocasiones, algunas funciones generan excepciones controladas para indicar errores en ciertas condiciones. Es crucial probar estos escenarios para asegurar la robustez de tu código.

Ejemplo con getStringLength

El método getStringLength lanza una ArgumentNullException si recibe un valor nulo. La prueba unitaria para este caso se estructura así:

var obj = new ClaseConLaFuncion(); // Nombre real de la clase
Assert.Throws<ArgumentNullException>(() => obj.GetStringLength(null));

Mediante Assert.Throws, verificamos que se lance la excepción correcta cuando se da una condición específica.

Prueba del método truncateString

Procedimientos similares aplican para el método truncateString. Este lanza una excepción si el parámetro maxLength es igual o menor a cero. Es recomendable crear una prueba para este flujo, asegurando que manejará las excepciones adecuadamente.

Consejos para mejorar tus pruebas unitarias

  • Comprueba distintas rutas de código: No todos los casos de uso son idénticos, así que asegúrate de cubrir los escenarios más relevantes.
  • Refactoriza y reutiliza el código de prueba: Busca patrones repetitivos que puedas abstraer para hacer el mantenimiento más sencillo.
  • Documenta tus pruebas: Anota de forma clara qué estás probando y por qué, lo cual es invaluable para la colaboración en equipo.

La práctica constante de probar ayudará a descubrir diferentes maneras de asegurar que tu código tenga el comportamiento esperado. Considera siempre ampliar tu suite de pruebas a medida que el código evoluciona para mantener la calidad. ¡Sigue practicando y mejora continuamente tus habilidades de codificación!

Aportes 11

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Estaría genial poder ampliar el video a lo largo de la ventana del explorador como el modo cine en youtube
Una duda, en mi caso no cree un objeto en cada clase si no que cree la instancia en el constructor para reutilizar codigo...enteindo que es una buena practica por la misma razon y ademas evita errores por otro lado me gustaria saber si esto es correcto segun las pruebas o puede haber alguna complicacion...gracias ejemplo:] ```c# public class StringOperationsTests { private readonly StringOperations stringOperations; public StringOperationsTests() { stringOperations = new StringOperations(); } [Fact] public void ConcatenateStrings() { var result = stringOperations.ConcatenateStrings("Perpetuo", "Beats"); Assert.Equal("Perpetuo Beats", result); } [Fact] public void ReverseString() { var result = stringOperations.ReverseString("Perpetuo Beats"); Assert.Equal("staeB outepreP", result); } ```public class StringOperationsTests { private readonly StringOperations stringOperations; public StringOperationsTests() { stringOperations = new StringOperations(); } \[Fact] public void ConcatenateStrings() { var result = stringOperations.ConcatenateStrings("Perpetuo", "Beats"); Assert.Equal("Perpetuo Beats", result); } \[Fact] public void ReverseString() { var result = stringOperations.ReverseString("Perpetuo Beats"); Assert.Equal("staeB outepreP", result); }
 [Fact]
        public void GetStringLength()
        {
            //Arrange
            var strStringManipulation = new StringOperations();
            //Act 
            var word = "New word";
            var result = strStringManipulation.GetStringLength(word);
            //Assert
            Assert.Equal(word.Length, result);
        }


        [Fact]
        public void TruncateString_Exception()
        {
            //Arrange
            var strStringManipulation = new StringOperations();
            //Act //Assert
            Assert.ThrowsAny<ArgumentOutOfRangeException>(() => strStringManipulation.TruncateString("Test",0));
        }
```js [Fact] public void GetStringLenght() { //arrange StringOperations strOperation = new(); //Act int result = strOperation.GetStringLength("Hello Edward"); //Assert Assert.Equal(12, result); } [Fact] public void TruncateStringTest_Exeption() { // arrange StringOperations strOperation = new(); //Act Action act = () => strOperation.TruncateString("Hello Edward", 0); //Assert Assert.ThrowsAny<ArgumentOutOfRangeException>(act); } } ``` \[Fact] public void GetStringLenght() { //arrange StringOperations strOperation = new(); //Act int result = strOperation.GetStringLength("Hello Edward"); //Assert Assert.Equal(12, result); } \[Fact] public void TruncateStringTest\_Exeption() { // arrange StringOperations strOperation = new(); //Act Action act = () => strOperation.TruncateString("Hello Edward", 0); //Assert Assert.ThrowsAny\<ArgumentOutOfRangeException>(act); } }
Una solucion de mantener A.A.A es usando delegados: ```js public void GetStringLenght_Exception() { //arrange StringOperations strOperation = new(); //Act Action act = () => strOperation.GetStringLength(null); //Assert Assert.Throws<ArgumentNullException>(act); } ``` public void GetStringLenght\_Exception() { //arrange StringOperations strOperation = new(); //Act Action act = () => strOperation.GetStringLength(null); //Assert Assert.Throws\<ArgumentNullException>(act); }
mi aporte\[Fact] public void GetStringLength() { var strOperations = new StringOperations(); var palabra = "hola"; var result = strOperations.GetStringLength(palabra); Assert.Equal(palabra.Length, result); } \[Fact] public void TruncateString\_Except() { var strOperations = new StringOperations(); Assert.Throws\<ArgumentOutOfRangeException>( () => strOperations.TruncateString("null", 0) ); } \[Fact] public void TruncateString\_MaxLength() { var strOperations = new StringOperations(); var palabra = "Hola Platzi"; var result = strOperations.TruncateString(palabra, 100); Assert.Equal(palabra, result); } \[Fact] public void TruncateString() { var strOperations = new StringOperations(); var palabra = "Hola Platzi"; var maxlengt = 4; var result = strOperations.TruncateString(palabra, maxlengt); Assert.Equal(palabra.Substring(0, maxlengt), result); } ```c# [Fact] public void GetStringLength() { var strOperations = new StringOperations(); var palabra = "hola"; var result = strOperations.GetStringLength(palabra); Assert.Equal(palabra.Length, result); } [Fact] public void TruncateString_Except() { var strOperations = new StringOperations(); Assert.Throws<ArgumentOutOfRangeException>( () => strOperations.TruncateString("null", 0) ); } [Fact] public void TruncateString_MaxLength() { var strOperations = new StringOperations(); var palabra = "Hola Platzi"; var result = strOperations.TruncateString(palabra, 100); Assert.Equal(palabra, result); } [Fact] public void TruncateString() { var strOperations = new StringOperations(); var palabra = "Hola Platzi"; var maxlengt = 4; var result = strOperations.TruncateString(palabra, maxlengt); Assert.Equal(palabra.Substring(0, maxlengt), result); } ```
una duda, en mi caso no cree un objeto para cada prueba si no que cree la instancia en el contructor de la clase, y funciona bien, entiendo que esto es una buena practica para re utilizar codigo y no repetir por otro lado me gustaria saber si es una buena opcion o por alguna razon es mejor crear un objeto en cada prueba? ejemplo: `public class StringOperationsTests` `{` ` private readonly StringOperations stringOperations;` ` public StringOperationsTests()` ` {` ` stringOperations = new StringOperations();` ` }` ` [Fact]` ` public void ConcatenateStrings()` ` {` ` var result = stringOperations.ConcatenateStrings("Perpetuo", "Beats");` ` Assert.Equal("Perpetuo Beats", result);` ` }` ` [Fact]` ` public void ReverseString()` ` {` ` var result = stringOperations.ReverseString("Perpetuo Beats");` ` Assert.Equal("staeB outepreP", result);` ` }`
Pero la funcion GetStringLength ya tiene tipado estático y no acepta null, además hasta el roslyn de visual studio te avisa que no puede pasarle null, porque validar si el parámetro str es null? Yo pienso que el siguiente código es válido si el str acepta string y null, pero este no es el caso. \~~~ public int GetStringLength(string str) { if(str is null) { throw new ArgumentNullException(); } return str.Length; } \~~~ Este sería la función que acepta null en el parámetro: \~~~ public int GetStringLength(string? str) { if(str is null) { throw new ArgumentNullException(); } return str.Length; } \~~~

Así quedaría el Test para la función TruncateString.

 [Fact]
 public void TruncateString_Exception()
 {
            var strOperations = new StringOperations();

            Assert.ThrowsAny<ArgumentOutOfRangeException>(()=>strOperations.TruncateString("Platzi", -2));

  }

Efectivamente el test es aprobado.

Así quedaría la prueba que no es una Excepción.

    [Fact]
    public void GetStringLength()
    {
            var strOperations = new StringOperations();

            var result = strOperations.GetStringLength("Platzi");

            Assert.True(result > 0);
        }

El test saldría así.

 [Fact]
        public void RemoveWhitespace()
        {
            var strOperations = new StringOperations();

            var result = strOperations.RemoveWhitespace("1    2 3     4  5    6 ");
            Assert.Equal("123456", result);
        }

Así quedó mi test