Mostrando entradas con la etiqueta tdd. Mostrar todas las entradas
Mostrando entradas con la etiqueta tdd. Mostrar todas las entradas

domingo, 5 de octubre de 2025

Programando en C# no.10 (usando xUnit)

Las pruebas unitarias nos ayudan a validar el funcionamiento de nuestro código. Se basan en el TDD o desarrollo basado en pruebas.

La filosofía del TDD se basa en:

  1. Escribir pruebas que fallen, se le da un color rojo. 
  2. Escribir pruebas que pasen, en color verde. 
  3. Refactorización, en azul.

Nosotros usaremos xUnit.

xUnit.net es una herramienta de prueba unitaria gratuita y de código abierto para .NET Framework (que se puede usar para C#, F# o Visual Basic).

Es similar a JUnit, pero para proyectos .NET.

Podemos hacer una breve comparativa.

Concepto xUnit (.NET/C#) JUnit (Java)
Lenguaje  C#  Java
Anotación de prueba [Fact] [Theory] @Test
Assert  Assert.Equal(), Assert.True()  Assertions.assertEquals(), etc.
Setup/Teardown  Constructor, IDisposable  @BeforeEach, @AfterEach
Organización  Por clase y métodos públicos  Por clase y métodos anotados
Ejecución  dotnet test  mvn test, gradle test, etc.

Instalamos algunos paquetes necesarios con Nuget (solo en caso de no tenerlos):

$ dotnet add package xunit
$ dotnet add package xunit.runner.visualstudio
$ dotnet add package Microsoft.NET.Test.Sdk

Comenzemos con una prueba sencilla. Una clase tiene un método para sumar dos números enteros. Crearemos una sencilla prueba para probar ese método.

1. Crear directorio del proyecto y ubicarnos en el.

$ mkdir Calculadora
$ cd Calculadora

2. Crear una solución con este comando:

$ dotnet new sln

3. Crear un proyecto de biblioteca:

$ dotnet new classlib -n Calculadora.Core

En este crearemos una clase llamada ``Calculadora.cs`` que tendrá el método de la suma de dos números enteros (y que posteriormente pondremos a prueba).

namespace Calculadora.Core;

public class Calculadora
{
    public int Sumar(int a, int b)
    {
        return a + b;
    }
}

4. Crear un proyecto de pruebas:

$ dotnet new xunit -n Calculadora.Tests

En este crearemos una clase ``CalculadoraTests.cs`` donde escribiremos dos métodos para probar el método de suma de la clase anterior.

using Xunit;
using Calculadora.Core; 

namespace Calculadora.Tests;

public class CalculadoraTests
{
    [Fact]
    public void Sumar_DosNumerosEnteros_RetornaSumaCorrecta()
    {
        // Arrange
        var calculadora = new Calculadora.Core.Calculadora(); 
        int a = 3;
        int b = 5;
        int esperado = 8;

        // Act
        int resultado = calculadora.Sumar(a, b);

        // Assert
        Assert.Equal(esperado, resultado);
    }

    [Fact]
    public void Sumar_NumerosNegativos_RetornaSumaCorrecta()
    {
        // Arrange
        var calculadora = new Calculadora.Core.Calculadora(); 
        int a = -2;
        int b = -3;
        int esperado = -5;

        // Act
        int resultado = calculadora.Sumar(a, b);

        // Assert
        Assert.Equal(esperado, resultado);
    }
}

Para los programadores Java que han usado JUnit esto les parecerá familiar.

5. Agregamos ambos proyectos a la solución:

$ dotnet sln add Calculadora.Core/Calculadora.Core.csproj
$ dotnet sln add Calculadora.Tests/Calculadora.Tests.csproj

6. Agregamos una referencia del proyecto Calculadora.Core al proyecto de pruebas Calculadora.Tests:

$ cd Calculadora.Tests
$ dotnet add reference ../Calculadora.Core/Calculadora.Core.csproj

7. Nos ubicamos en la raíz del proyecto (Calculadora):

Calculadora/
├── Calculadora.Core/
│   ├── Calculadora.cs
│   └── Calculadora.Core.csproj
├── Calculadora.Tests/
│   ├── CalculadoraTests.cs
│   └── Calculadora.Tests.csproj
└── Calculadora.sln

8. Abrimos una terminal y ejecutamos la prueba:

$ dotnet test

Salida:

Iniciando la ejecución de pruebas, espere...
1 archivos de prueba en total coincidieron con el patrón especificado.

Correctas! - Con error:     0, Superado:     2, Omitido:     0, Total:     2, Duración: 8 ms - Calculadora.Tests.dll (net8.0)

¡Hemos creado nuestras primeras pruebas unitarias con xUnit!

Si tienes problemas ejecuta estos comandos uo por uno para limpiar, compilar y ejecutar el proyecto:

$ dotnet clean
$ dotnet restore
$ dotnet build
$ dotnet test

Enlaces:

https://learn.microsoft.com/es-es/dotnet/core/testing/unit-testing-csharp-with-xunit
https://es.wikipedia.org/wiki/XUnit
https://xunit.net/?tabs=cs
https://dev.to/maadcode/introduccion-a-xunit-una-poderosa-herramienta-para-unit-testing-en-net-34b0

viernes, 25 de noviembre de 2011

TDD… ejemplos básicos



Es una técnica de programación que emplea pruebas unitarias y refactorización de código.


El ciclo de vida de TDD comprende tres etapas

  1. Escribir una prueba que falle (rojo)
  2. Escribir una prueba que pase (verde)
  3. Refactorización, mejorar el código sin afectar su funcionamiento interno


Problema. Obtener el número de pulsaciones de una persona con 15 segundos de ejercitación.

Entrada: edad de la persona
Salida: número de pulsaciones
Restricciones o casos posibles:
  1. la edad no debe ser cero o un valor negativo,
  2. un valor flotante (ej. 4.5)
  3. o un carácter.

Fórmula. Num_pulsaciones = (220 – edad)/15

El primer paso es crear una prueba que falle, existen libros sobre TDD y Refactorización que indican la forma realizar los test, pero bien lo trataré de hacer según mi entendimiento.

PulsacionTest. Java

@Test
public void testObtenerPulsaciones() {
Pulsacion pulsacion = new Pulsacion();
System.out.println("obtenerPulsaciones: entero positivo");
int edad = 26;
double expResult = 12.0;
assertEquals(expResult, pulsacion.obtenerPulsaciones(edad), 0.0);
}

Obvio es que falle (no tengo que probar). Ahora el segundo paso es crear el código necesario (Pulsacion.java) para pasar la prueba.


//Código inicial
Pulsacion.java

public double obtenerPulsaciones(int edad){
return (220-edad)/15;
}

Listo pasa la primer prueba (valor entero no negativo). Ahora otro problema, es necesario realizar pruebas para los tres casos posibles (valor cero o negativo, valor flotante, o carácter).

Para ahorrar líneas de código defino “pulsación” como un atributo de la clase PulsacionTest.java para que sea accesible para los demás métodos.

He aquí el código aplicando TDD y un poco de Refactorización.

PulsacionTest. Java

Pulsacion pulsacion = new Pulsacion();

//para un valor entero no negativo
@Test
public void testObtenerPulsaciones() {
System.out.println("obtenerPulsaciones: entero positivo");
int edad = 26;
double expResult = 12.0;
assertEquals(expResult, pulsacion.obtenerPulsaciones(edad), 0.0);
}

// para un valor cero o negativo
@Test
public void testObtenerPulsacionesNegativoCero(){
System.out.println("obtenenerPulsaciones: cero o negativo");
int edad_neg=-26;
double expResult1=14.0;
assertEquals(expResult1, pulsacion.obtenerPulsaciones(edad_neg), 0.0);
}

// para un valor flotante
@Test
public void testObtenerPulsacionesReal(){
System.out.println("obtenenerPulsaciones: real");
double edad_real=26.0;
double expResult2=12.0;
assertEquals(expResult2, pulsacion.obtenerPulsaciones((int)edad_real), 0.0);
}

//para un carácter
@Test
public void testObtenerPulsacionesCaracter(){
System.out.println("obtenenerPulsaciones: caracter");
String edad_cad="26";
double expResult3=12.0;
assertEquals(expResult3, pulsacion.obtenerPulsaciones(Integer.parseInt(edad_cad)), 0.0);
}

En este método se podría agregar otro método que compruebe si la cadena introducida es numérica o no.


public bolean esNumerico (String cad){
try{
Integer.parseInt (cad);
return true;

}catch(NumberFormatException ex){
return false;}
}
//Código final
Pulsacion.java

public double obtenerPulsaciones(int edad){
if((int)edad<=0){
return (220-0)/15;
}
else if((int)edad>0){
return (220-(int)edad)/15;
}
else{
return (220-edad)/15;
}
}

Jai un lenguaje de programación inspirado en C++

Hoy hablaremos de un nuevo lenguaje de programación llamado Jai . Se trata de un lenguaje de programación que está desarrolland...

Etiquetas

Archivo del blog