Organización y prueba de proyectos con la CLI de .NET

En este tutorial es una continuación de lo establecido en Tutorial: Creación de una aplicación de consola con .NET en Visual Studio Code, por lo que le llevará más allá de la creación de una aplicación de consola simple para desarrollar aplicaciones avanzadas y bien organizadas. Después de mostrarle cómo usar carpetas para organizar su código, este tutorial le muestra cómo ampliar una aplicación de consola con el marco de pruebas de xUnit.

Nota

En este tutorial se recomienda colocar el proyecto de aplicación y el proyecto de prueba en carpetas independientes. Algunos desarrolladores prefieren mantener estos proyectos en la misma carpeta. Para más información, consulte la incidencia de GitHub dotnet/docs #26395.

Uso de carpetas para organizar el código

Si quiere introducir nuevos tipos en una aplicación de consola, puede hacerlo agregando archivos que contienen los tipos en la aplicación. Por ejemplo, si agrega archivos que contienen tipos AccountInformation y MonthlyReportRecords en su proyecto, la estructura del archivo del proyecto es plana y resulta fácil desplazarse por ella:

/MyProject
|__AccountInformation.cs
|__MonthlyReportRecords.cs
|__MyProject.csproj
|__Program.cs

Sin embargo, esta estructura plana solo funciona bien cuando el tamaño del proyecto es relativamente pequeño. ¿Puede imaginar qué pasará si agrega 20 tipos al proyecto? Definitivamente no será fácil desplazarse por el proyecto ni mantenerlo con tantos archivos depositados en el directorio raíz del proyecto.

Para organizar el proyecto, cree una carpeta nueva y denomínela Models para contener los archivos de tipo. Coloque los archivos de tipo en la carpeta Models:

/MyProject
|__/Models
   |__AccountInformation.cs
   |__MonthlyReportRecords.cs
|__MyProject.csproj
|__Program.cs

Es fácil desplazarse por los proyectos que agrupan archivos en carpetas de manera lógica, así como mantenerlos. En la sección siguiente, creará un ejemplo más complejo con carpetas y pruebas unitarias.

Organizar y probar con el ejemplo de NewTypes Pets

Requisitos previos

Compilar el ejemplo

Para los pasos siguientes, puede seguir con el ejemplo de NewTypes Pets o crear sus propios archivos y carpetas. Los tipos se organizan de manera lógica en una estructura de carpetas que permite la adición de más tipos posteriormente, y las pruebas también se colocan de manera lógica en carpetas que permiten la adición de más pruebas después.

El ejemplo contiene dos tipos, Dog y Cat, y tiene implementada una interfaz común, IPet. Para el proyecto NewTypes, su objetivo es organizar los tipos relacionados con las mascotas en una carpeta Pets. Si se agrega después otro conjunto de tipos, WildAnimals por ejemplo, se colocan en la carpeta NewTypes junto a la carpeta Pets. La carpeta WildAnimals puede contener tipos de animales que no son mascotas, como los tipos Squirrel y Rabbit. De la manera en que se agregan los tipos, el proyecto sigue estando bien organizado.

Cree la siguiente estructura de carpetas con el contenido del archivo indicado:

/NewTypes
|__/src
   |__/NewTypes
      |__/Pets
         |__Dog.cs
         |__Cat.cs
         |__IPet.cs
      |__Program.cs
      |__NewTypes.csproj

IPet.cs:

using System;

namespace Pets
{
    public interface IPet
    {
        string TalkToOwner();
    }
}

Dog.cs:

using System;

namespace Pets
{
    public class Dog : IPet
    {
        public string TalkToOwner() => "Woof!";
    }
}

Cat.cs:

using System;

namespace Pets
{
    public class Cat : IPet
    {
        public string TalkToOwner() => "Meow!";
    }
}

Program.cs:

using System;
using Pets;
using System.Collections.Generic;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            List<IPet> pets = new List<IPet>
            {
                new Dog(),
                new Cat()
            };

            foreach (var pet in pets)
            {
                Console.WriteLine(pet.TalkToOwner());
            }
        }
    }
}

NewTypes.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Ejecute el siguiente comando:

dotnet run

Obtenga el siguiente resultado:

Woof!
Meow!

Ejercicio opcional: puede agregar un nuevo tipo de mascota, como Bird, si amplía este proyecto. Haga que el método TalkToOwner de las aves proporcione Tweet! al propietario. Ejecute la aplicación de nuevo. El resultado incluirá Tweet!.

Probar el ejemplo

El proyecto NewTypes está en su lugar y lo ha organizado manteniendo los tipos relacionados con las mascotas en una carpeta. Después, cree su proyecto de prueba y comience a escribir pruebas con el marco de pruebas de xUnit. Las pruebas unitarias le permiten comprobar automáticamente el comportamiento de sus tipos de mascota para confirmar que están funcionando correctamente.

Vuelva a la carpeta src y cree una carpeta test con una carpeta NewTypesTests en su interior. En un símbolo del sistema desde la carpeta NewTypesTests, ejecute dotnet new xunit. Este comando genera dos archivos: NewTypesTests.csproj y UnitTest1.cs.

El proyecto de prueba no puede probar actualmente los tipos de NewTypes y necesita una referencia del proyecto para el proyecto NewTypes. Para agregar una referencia del proyecto, use el comando dotnet add reference:

dotnet add reference ../../src/NewTypes/NewTypes.csproj

O bien, también tiene la opción de agregar manualmente la referencia del proyecto si agrega un nodo <ItemGroup> al archivo NewTypesTests.csproj:

<ItemGroup>
  <ProjectReference Include="../../src/NewTypes/NewTypes.csproj" />
</ItemGroup>

NewTypesTests.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
    <PackageReference Include="xunit" Version="2.7.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.8" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="../../src/NewTypes/NewTypes.csproj"/>
  </ItemGroup>

</Project>

El archivo NewTypesTests.csproj contiene las siguientes referencias de paquetes:

  • Microsoft.NET.Test.Sdk, la infraestructura de pruebas de .NET
  • xunit, el marco de pruebas de xUnit
  • xunit.runner.visualstudio, el ejecutor de las pruebas
  • NewTypes, el código que se va a probar

Cambie el nombre de UnitTest1.cs a PetTests.cs y reemplace el código del archivo por el siguiente:

using System;
using Xunit;
using Pets;

public class PetTests
{
    [Fact]
    public void DogTalkToOwnerReturnsWoof()
    {
        string expected = "Woof!";
        string actual = new Dog().TalkToOwner();

        Assert.NotEqual(expected, actual);
    }

    [Fact]
    public void CatTalkToOwnerReturnsMeow()
    {
        string expected = "Meow!";
        string actual = new Cat().TalkToOwner();

        Assert.NotEqual(expected, actual);
    }
}

Ejercicio opcional: si ha agregado un tipo Bird anteriormente que da como resultado Tweet! para el propietario, agregue un método de prueba al archivo PetTests.cs, BirdTalkToOwnerReturnsTweet, para comprobar que el método TalkToOwner funciona correctamente para el tipo Bird.

Nota

Aunque espere que los valores expected y actual sean iguales, la aserción inicial con la comprobación Assert.NotEqual especifica que estos valores no son iguales. Cree siempre inicialmente una prueba que resulte fallida para comprobar la lógica de la prueba. Después de confirmar que la prueba falla, ajuste la aserción para permitir que se supere la prueba.

A continuación se muestra la estructura del proyecto completo:

/NewTypes
|__/src
   |__/NewTypes
      |__/Pets
         |__Dog.cs
         |__Cat.cs
         |__IPet.cs
      |__Program.cs
      |__NewTypes.csproj
|__/test
   |__NewTypesTests
      |__PetTests.cs
      |__NewTypesTests.csproj

Comience en el directorio test/NewTypesTests. Ejecute las pruebas con el comando dotnet test. Este comando inicia el ejecutor de pruebas especificado en el archivo del proyecto.

Como se esperaba, se producen errores en las pruebas y la consola muestra el siguiente resultado:

Test run for C:\Source\dotnet\docs\samples\snippets\core\tutorials\testing-with-cli\csharp\test\NewTypesTests\bin\Debug\net5.0\NewTypesTests.dll (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.8.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.50]     PetTests.DogTalkToOwnerReturnsWoof [FAIL]
  Failed PetTests.DogTalkToOwnerReturnsWoof [6 ms]
  Error Message:
   Assert.NotEqual() Failure
Expected: Not "Woof!"
Actual:   "Woof!"
  Stack Trace:
     at PetTests.DogTalkToOwnerReturnsWoof() in C:\Source\dotnet\docs\samples\snippets\core\tutorials\testing-with-cli\csharp\test\NewTypesTests\PetTests.cs:line 13

Failed!  - Failed:     1, Passed:     1, Skipped:     0, Total:     2, Duration: 8 ms - NewTypesTests.dll (net5.0)

Cambie las aserciones de sus pruebas de Assert.NotEqual a Assert.Equal:

using System;
using Xunit;
using Pets;

public class PetTests
{
    [Fact]
    public void DogTalkToOwnerReturnsWoof()
    {
        string expected = "Woof!";
        string actual = new Dog().TalkToOwner();

        Assert.Equal(expected, actual);
    }

    [Fact]
    public void CatTalkToOwnerReturnsMeow()
    {
        string expected = "Meow!";
        string actual = new Cat().TalkToOwner();

        Assert.Equal(expected, actual);
    }
}

Vuelva a ejecutar las pruebas con el comando dotnet test y obtenga el siguiente resultado:

Test run for C:\Source\dotnet\docs\samples\snippets\core\tutorials\testing-with-cli\csharp\test\NewTypesTests\bin\Debug\net5.0\NewTypesTests.dll (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.8.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:     2, Skipped:     0, Total:     2, Duration: 2 ms - NewTypesTests.dll (net5.0)

Se pasan las pruebas. Los métodos de los tipos de mascota devuelven los valores correctos al dirigirse al propietario.

Ha obtenido información sobre las técnicas para organizar y probar proyectos con xUnit. Continúe con estas técnicas aplicándolas en sus propios proyectos. Disfrute programando.