Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Атрибуты в модульных тестах C#
В C# для написания модульных тестов (преимущественно с использованием фреймворков xUnit, NUnit или MSTest) существует множество атрибутов, которые позволяют управлять поведением тестов, их структурой и исполнением. Эти атрибуты делятся на несколько категорий.
Основные атрибуты для обозначения тестов
В xUnit:
[Fact]— помечает метод как тестовый без параметров.[Theory]— помечает параметризованный тест, который может выполняться с разными данными.[InlineData]— предоставляет данные для параметризованного теста прямо в атрибуте.
public class CalculatorTests
{
[Fact]
public void Add_TwoNumbers_ReturnsSum()
{
var result = 2 + 3;
Assert.Equal(5, result);
}
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, -2, -3)]
public void Add_Parameterized_ReturnsCorrectSum(int a, int b, int expected)
{
var result = a + b;
Assert.Equal(expected, result);
}
}
В NUnit:
[Test]— аналог[Fact]в xUnit.[TestCase]— аналог комбинации[Theory]и[InlineData].
В MSTest:
[TestMethod]— основной атрибут для тестового метода.[DataTestMethod]и[DataRow]— для параметризованных тестов.
Атрибуты для управления жизненным циклом тестов
Эти атрибуты позволяют выполнять код до/после тестов.
Общие (в зависимости от фреймворка):
- xUnit:
[Fact]не поддерживает явные методы setup/teardown на уровне класса, но естьIClassFixture<T>иICollectionFixture<T>для общих ресурсов. Для методов используется конструктор (аналог setup) иIDisposable(аналог teardown). - NUnit:
[SetUp],[TearDown](для методов),[OneTimeSetUp],[OneTimeTearDown](для класса). - MSTest:
[TestInitialize],[TestCleanup](для методов),[ClassInitialize],[ClassCleanup](для класса).
Пример в NUnit:
[TestFixture]
public class LifecycleTests
{
[OneTimeSetUp]
public void ClassSetup() { /* выполняется один раз перед всеми тестами */ }
[SetUp]
public void MethodSetup() { /* выполняется перед каждым тестом */ }
[Test]
public void Test1() { /* тест */ }
[TearDown]
public void MethodTeardown() { /* выполняется после каждого теста */ }
[OneTimeTearDown]
public void ClassTeardown() { /* выполняется один раз после всех тестов */ }
}
Атрибуты для организации тестов
[Trait](xUnit) /[Category](NUnit) /[TestCategory](MSTest) — для категоризации тестов (например, "Интеграционные", "Быстрые").[Collection](xUnit) — группирует тестовые классы для общего контекста.[TestFixture](NUnit) — помечает класс как содержащий тесты.[TestClass](MSTest) — аналог[TestFixture].
Атрибуты для настройки поведения тестов
[Skip](xUnit) /[Ignore](NUnit, MSTest) — временно отключает тест.[Timeout](NUnit, MSTest) — устанавливает таймаут для теста.[Retry](NUnit) — повторяет тест при неудаче.[Repeat](NUnit) — повторяет тест указанное количество раз.[Order](NUnit, MSTest) — задает порядок выполнения тестов (хотя это считается антипаттерном).[NonParallelizable](NUnit) — запрещает параллельное выполнение теста.
Пример с [Retry] в NUnit:
[Test]
[Retry(3)]
public void UnstableTest()
{
// Тест будет повторен до 3 раз при неудаче
}
Атрибуты для интеграционного тестирования
[AutoData]/[Frozen]/[Greedy]— из библиотеки AutoFixture для автоматической генерации тестовых данных.[Mock]— из Moq или других библиотек для внедрения mock-объектов (часто используются с фреймворками вроде AutoFixture.AutoMoq).
Кастомные атрибуты
Вы можете создавать собственные атрибуты, наследуясь от базовых (например, [DataAttribute] в xUnit), чтобы расширить функционал. Например, для чтения тестовых данных из JSON-файла:
public class JsonFileDataAttribute : DataAttribute
{
private readonly string _filePath;
public JsonFileDataAttribute(string filePath)
{
_filePath = filePath;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
var json = File.ReadAllText(_filePath);
var data = JsonConvert.DeserializeObject<List<object[]>>(json);
return data;
}
}
// Использование
[Theory]
[JsonFileData("testdata.json")]
public void TestWithExternalData(int a, int b, int expected)
{
Assert.Equal(expected, a + b);
}
Атрибуты для асинхронных тестов
В современных версиях фреймворков можно просто возвращать Task из тестового метода, но есть и специализированные атрибуты, например:
[AsyncTimeout]в NUnit для асинхронных таймаутов.
Важные замечания
- Фреймворк-специфичные атрибуты не взаимозаменяемы между xUnit, NUnit и MSTest.
- Атрибуты компиляции — некоторые атрибуты (например,
[Conditional]) могут влиять на включение тестов в сборку. - Приоритет выполнения — атрибуты жизненного цикла имеют четкий порядок, который важно понимать для корректной инициализации и очистки ресурсов.
Использование правильных атрибутов делает тесты более структурированными, поддерживаемыми и эффективными, особенно в крупных проектах с сотнями или тысячами тестов.