Search  
Always will be ready notify the world about expectations as easy as possible: job change page
27 декабря 2022 г.

Как правильно выбрать название для Unit тестов

Author:
Artem Polishchuk
Source:
Views:
1175

Часто бывает что вам нужно протестировать какую то функцию или метод, однако подобрать имя для теста бывает часто затруднительно. Для этого в этой статье мы рассмотрим несколько самых используемых подходов к именованию Unit тестов.

Ниже приведены несколько популярных условных обозначений, которые, как установлено, используются большинством разработчиков:

MethodName_StateUnderTest_ExpectedBehavior: ​

Существуют аргументы против этой стратегии, так как если имена методов изменяются после рефакторинга кода, это должно также изменить название теста, это становится трудным для понимания на более позднем этапе. Ниже приведены некоторые примеры:

public void IsAdult_AgeLessThan18_False()
{
}

 

public void WithdrawMoney_InvalidAccount_ExceptionThrown()
{
}

 

public void AdmitStudent_MissingMandatoryFields_FailToAdmit()
{
}

MethodName_ExpectedBehavior_StateUnderTest:

Этот вариант слегка отличается от предыдущего, но разработчики также рекомендует использовать этот метод именования. Этот метод имеет тот же недостаток что и предыдущий, если имена методов изменяются, становится сложнее разобраться в названиях на позднем этапе. Ниже приведен пример того, как тесты из первого примера будут читаться, как если бы эти имена использовались с использованием этого метода:

public void IsAdult_False_AgeLessThan18()
{
}

 

public void WithdrawMoney_ThrowsException_IfAccountIsInvalid()
{
}

 

public void AdmitStudent_FailToAdmit_IfMandatoryFieldsAreMissing()
{
}

Feature to be tested:

Многие полагают, что лучше просто написать тестируемую функцию, потому что в любом случае вы используете аннотации, чтобы идентифицировать метод в качестве методов тестирования. Он также рекомендуется по той причине, что он делает модульные тесты альтернативной формой документации и не так портит кода. И опять таки примеры с использованием этого метода:

public void IsNotAnAdultIfAgeLessThan18()
{
}

 

public void FailToWithdrawMoneyIfAccountIsInvalid()
{
}

 

public void StudentIsNotAdmittedIfMandatoryFieldsAreMissing()
{
}

Should_ExpectedBehavior_When_StateUnderTest:

Этот метод также используется многими, так как он легко объясняет что должна делать тестируемая функция. Примеры:

public void Should_ThrowException_When_AgeLessThan18()
{
}

 

public void Should_FailToWithdrawMoney_ForInvalidAccount()
{
}

 

public void Should_FailToAdmit_IfMandatoryFieldsAreMissing()
{
}

When_StateUnderTest_Expect_ExpectedBehavior:

Аналогично предыдущему, но условие теперь стоит перед ожидаемым выполнением. Примеры:

public void When_AgeLessThan18_Expect_isAdultAsFalse()
{
}

 

public void When_InvalidAccount_Expect_WithdrawMoneyToFail()
{
}

 

public void When_MandatoryFieldsAreMissing_Expect_StudentAdmissionToFail()
{
}

​​​Given_Preconditions_When_StateUnderTest_Then_ExpectedBehavior:

Этот подход основан на стандартах именовании, разработанном как часть Behavior-Driven Development (BDD). Идея состоит в том, чтобы разбить тесты на три части таким образом, чтобы можно было найти предварительные условия, проверка состояния во время теста и ожидаемое поведение, которое должно быть написано в вышеуказанном формате. Ниже приведен пример того, как если бы эти имена использовались с использованием этого метода:

public void Given_UserIsAuthenticated_When_InvalidAccountNumberIsUsedToWithdrawMoney_Then_TransactionsWillFail()
{
}

MethodName_WithStateUnderTest_ShouldExpectedBehavior: ​ 

Этот подход похож на MethodName_StateUnderTest_ExpectedBehavior, но лично мне импонирует больше всего. Понятно какой метод под тестом, с какими данными и что должен вернуть в итоге.

Давайте рассмотрим пример:

[Test]
public void Login_WithDisabledTwoFactorSmsAuth_ShouldReturnSignInAndReturnRedirectToActionResult()
{
    // Arange
    var model = new LoginModel
    {
        Email = "admin@test.com",
        Password = "q1w2e3"
    };

    Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    configuration.AppSettings.Settings[key].Value = value;
    configuration.Save();
    ConfigurationManager.RefreshSection("appSettings");

    // Act
    var result = Controller.Login(model, null).Result;

    // Assert
    Assert.IsInstanceOf<RedirectToRouteResult>(result);
}
Similar
15 марта
Автор: Рустем Галиев
Blazor — это технология, позволяющая создавать клиентские веб-приложения с использованием C# и .NET, а не JavaScript. Blazor может запускать ваш код одним из двух способов. Blazor WebAssembly выполняет код C# на стороне клиента в любом современном браузере, поддерживающем WebAssembly. Blazor...
Mar 10, 2023
Author: Yohan Malshika
Writing unit test code when using the Dapper ORM tool for database operations with ASP.NET Core Web ApplicationHow to write unit tests with DapperWriting unit tests when using the Dapper ORM tool for database operations in an ASP.NET Core Web...
24 марта
Автор: Сергей Кушниренко
Среди множества задач, решаемых программистом, одной из самых частых является подумать и добавить новый функционал в приложение. И там уже может быть много похожего функционала, он может быть хорошо написан, хорошо документирован. Искушение заключается в том, поддаться своей лени и...
24 марта
Автор: Олег Борисенков
Рассказываем какие существуют стили именования переменных и зачем они нужны.Чтобы обеспечить легкую читаемость кода программисты используют разные стили именования для разных типов объектов, функций и переменных. Именно поэтому нет какого-то одного «идеального» формата. Выбор уместного стиля поможет быстро понять к...
Send message
Email
Your name
*Message


© 1999–2024 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET Framework | .NET Core | C# | ASP.NET | Windows Forms | WPF | HTML5 | CSS3 | jQuery | AJAX | Angular | React | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban