Написание модульных тестов — хорошая практика разработки программного обеспечения. В этой статье мы узнаем, как создать приложение C # .NET Core, придерживаясь подхода Test Driven Development (TDD). В подходе TDD перед реализацией функциональности вы пишете для нее модульный тест. Например, если вы хотите написать функцию для добавления двух чисел, сначала вы напишите проваленный модульный тест, а затем реализуете функциональность для прохождения теста.
В этом посте мы создадим приложение калькулятора. Для начала, давайте следовать структуре папок, как показано ниже:
- CalculatorApp — Решение
- CalculatorApp.Services — Проект приложения
- CalculatorApp.Services.Tests — Тестовый проект
Вы можете использовать Visual Studio для создания проектов; однако в этом посте я буду использовать команды .NET Core для создания своих проектов, добавления тестов и запуска тестов. Вы также можете использовать MSTest или NUnit для написания модульных тестов, но в этом примере я буду использовать xUnit и dotnet test для написания и запуска своих модульных тестов.
Давайте начнем с открытия командной оболочки и продолжим:
Создание проекта приложения
Для начала вам нужно создать каталог с именем CalculatorApp . Имейте в виду, что вы можете следовать любому соглашению об именах, которое вы хотите для каталогов, но если вы хотите следовать этому посту, я бы рекомендовал использовать то же имя каталога. Итак, давайте создадим каталог CalculatorApp и перейдем к нему.
Внутри каталога CalculatorApp мы собираемся создать новое решение, выполнив следующую команду:
dotnet new sln
После успешного выполнения команды вы должны получить сообщение «Файл решения шаблона создан успешно». Также внутри каталога CalculatorApp вы найдете файл с именем calculatorapp.sln.
Затем создайте каталог с именем CalculatorApp.Services. В этом каталоге будут храниться исходные коды приложения, т.е. все классы приложения калькулятора. Перейдите в каталог Calculatorapp.Services и создайте библиотеку классов, выполнив следующую команду:
dotnet new classlib
После успешного выполнения этой команды вы должны получить сообщение «Библиотека классов шаблонов создана успешно». Вы также найдете файл с именем calculatorapp.services.csproj в каталоге CalculatorApp.Services. Затем вам нужно добавить этот проект библиотеки классов в решение calculatorapp. Для этого вернитесь обратно в каталог calculatorapp и выполните команду:
dotnet sln add .\calculatorapp.services\calculatorapp.services.csproj
После успешного выполнения команды вы должны получить сообщение «Проект добавлен в решение».
Внутри папки CalculatorApp.Services вы найдете класс Class1 — переименуйте его в Calculator и измените класс, как показано в листинге ниже:
Calculator.cs
using System;
namespace calculatorapp.services
{
public class Calculator
{
public int Add(int num1, int num2)
{
throw new NotImplementedException();
}
public int Sub(int num1, int num2)
{
throw new NotImplementedException();
}
}
}
В приведенном выше листинге вы заметите, что функции Add и Sub не реализованы. Сначала мы напишем модульный тест, а затем реализуем эти функции.
Создание тестового проекта
Чтобы добавить тестовые проекты, создайте каталог с именем CalculatorApp.Services.Tests и перейдите в каталог. В этом каталоге мы создадим проект MS Test, выполнив следующую команду:
dotnet new mstest
Эта команда создает тестовый проект, который использует MS Test в качестве тестовой библиотеки. После создания тестового проекта добавьте библиотеку исходного проекта в тестовый проект. Для этого выполните команду:
dotnet add reference ../CalculatorApp.Services/CalculatorApp.Services.csproj
Эта команда добавит ссылку на проект CalculatorAppService в тестовый проект. После добавления ссылки добавьте тестовый проект в решение, перейдя в корневой каталог calculatorapp и выполните команду:
dotnet sln add .\CalculatorAppServices.tests\CalculatorAppServices.Tests.csproj
Эта команда добавит тестовый проект в решение. После успешного выполнения команды вы должны получить сообщение «Проект добавлен в решение».
Написание юнит-тестов
Итак, мы создали исходный проект приложения и тестовый проект. В исходном проекте приложения есть нереализованные функции. Теперь давайте напишем тесты для этих функций.
В тестовом проекте я переименовал файл UnitTest1.cs в Calculator.Test.cs, а имя класса в CalculatorTest. В конструкторе CalculatorTest нам нужно создать объект класса Calculator. Это можно сделать, как показано в листинге ниже:
Calculator.Test.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using calculatorapp.services;
namespace CalculatorApp.Services.Tests
{
[TestClass]
public class CalculatorTest
{
Calculator _calc;
public CalculatorTest()
{
_calc = new Calculator();
}
}
}
Модульный тест для добавления функции
В классе CalculatorTest добавьте метод модульного тестирования, чтобы проверить функциональность добавления, как показано в листинге ниже:
[TestMethod]
public void shouldaddtwonumbers()
{
int res = _calc.Add(5, 3);
Assert.AreEqual(res, 8);
}
Для запуска теста перейдите в каталог CalculatorApp.Services.Tests и выполните команду:
dotnet test
Вы получите вывод «test fail», потому что функция Add не реализована, как показано на рисунке ниже:
Чтобы пройти тест, реализуйте функцию Add в классе Calculator, как показано в листинге ниже:
public int Add(int num1, int num2)
{
int result = num1 + num2;
return result;
}
Чтобы запустить тест сейчас, перейдите к директору CalculatorApp.Services.Tests и выполните команду:
dotnet test
В качестве вывода вы получите сообщение «тест пройден», как показано на рисунке ниже:
Теперь вы реализовали функцию добавления, придерживаясь подхода TDD в приложении .NET Core!
Модульный тест для подфункции
В классе CalculatorTest добавьте метод модульного тестирования, чтобы проверить подфункцию, как показано в листинге ниже:
[TestMethod]
public void shouldsubstracttwonumbers()
{
int res = _calc.Sub(5, 3);
Assert.AreEqual(res, 2);
}
Для запуска теста перейдите в каталог CalculatorApp.Services.Tests и выполните команду:
dotnet test
Здесь ваш тест не пройден, потому что функция Sub не реализована. Вы получите один результат неудачного теста, как показано на рисунке ниже:
Чтобы пройти тест, внедрите функцию Sub в классе Calculator, как показано в листинге ниже:
public int Sub(int num1, int num2)
{
int result = num1 - num2;
return result;
}
Теперь снова запустите тест, перейдя в каталог CalculatorApp.Services.Tests и выполнив:
dotnet test
Теперь вы увидите, что оба теста пройдены, как показано здесь:
Теперь вы реализовали Sub-функциональность, придерживаясь подхода TDD в приложении .NET Core.
Завершение
До сих пор в этом посте мы создали приложение .NET Core Calculator, придерживаясь подхода TDD. Для создания тестов мы использовали тесты XUnit и dotnet. Для справки, вот исходный код класса Calculator и его тестового класса:
Calculator.cs
using System;
namespace calculatorapp.services
{
public class Calculator
{
public int Add(int num1, int num2)
{
int result = num1 + num2;
return result;
}
public int Sub(int num1, int num2)
{
int result = num1 - num2;
return result;
}
}
}
Calculator.test.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using calculatorapp.services;
namespace CalculatorApp.Services.Tests
{
[TestClass]
public class CalculatorTest
{
Calculator _calc;
public CalculatorTest()
{
_calc = new Calculator();
}
[TestMethod]
public void shouldaddtwonumbers()
{
int res = _calc.Add(5, 3);
Assert.AreEqual(res, 8);
}
[TestMethod]
public void shouldsubstracttwonumbers()
{
int res = _calc.Sub(5, 3);
Assert.AreEqual(res, 2);
}
}
}
И вот как вы пишете модульные тесты, а затем реализуете их функциональные возможности. Я надеюсь, что этот пост поможет вам начать писать модульные тесты для вашего следующего приложения .NET Core!