Какие атрибуты для написания тестов в C# вы используете чаще всего?

«Какие атрибуты для написания тестов в C# вы используете чаще всего?» — вопрос из категории Тестирование, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Я преимущественно работаю с xUnit как с наиболее гибким и современным фреймворком для .NET. Вот ключевые атрибуты и их применение:

Основные атрибуты xUnit:

  • [Fact] – помечает метод как тестовый, который должен выполняться без внешних данных.
    [Fact]
    public void CalculateTotal_EmptyCart_ReturnsZero()
    {
        var cart = new ShoppingCart();
        var total = cart.CalculateTotal();
        Assert.Equal(0, total);
    }
  • [Theory] – помечает параметризованный тест. Данные для него предоставляются отдельными атрибутами.
  • [InlineData] – самый простой способ передать данные в [Theory]. Данные задаются прямо в атрибуте.
    [Theory]
    [InlineData(5, 3, 8)]  // a, b, expected
    [InlineData(-1, 1, 0)]
    [InlineData(0, 0, 0)]
    public void Add_TwoNumbers_ReturnsSum(int a, int b, int expected)
    {
        var calculator = new Calculator();
        var result = calculator.Add(a, b);
        Assert.Equal(expected, result);
    }
  • [MemberData] – позволяет использовать статическое свойство или метод класса для предоставления сложных наборов тестовых данных (например, объекты).

    public static IEnumerable<object[]> TestData =>
        new List<object[]>
        {
            new object[] { new User("Alice", 30), true },
            new object[] { new User("Bob", 17), false }
        };
    
    [Theory]
    [MemberData(nameof(TestData))]
    public void User_IsAdult_ReturnsCorrectValue(User user, bool expectedIsAdult)
    {
        var result = user.IsAdult();
        Assert.Equal(expectedIsAdult, result);
    }
  • [ClassData] – похож на [MemberData], но данные предоставляет отдельный класс, реализующий IEnumerable<object[]>. Удобно для организации больших наборов данных.

Атрибуты для управления выполнением:

  • [Trait("Category", "Integration")] – для категоризации тестов (например, чтобы запускать только "Unit" или только "Integration" тесты в пайплайне).
  • [Fact(Skip = "Требуется доработка моков")] – временно отключает тест.

Сравнение с другими фреймворками:

  • NUnit: [Test] (аналог [Fact]), [TestCase] (аналог [InlineData]).
  • MSTest: [TestMethod], [DataTestMethod], [DataRow].

Практический совет: Используйте [Theory] с [MemberData] или [ClassData] для тестирования пограничных случаев (boundary values) и различных сценариев, чтобы избежать дублирования кода тестов.