Каковы некоторые популярные соглашения об именах для модульных тестов?

генеральный

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

Примеры

1) MethodName_StateUnderTest_ExpectedBehavior

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown() 

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () 

Public void Sum_simpleValues_Calculated ()

Источник: Стандарты именования для модульных тестов.

2) Разделение каждого слова подчеркиванием

Public void Sum_Negative_Number_As_1st_Param_Exception_Thrown() 

Public void Sum_Negative_Number_As_2nd_Param_Exception_Thrown () 

Public void Sum_Simple_Values_Calculated ()

Другой

  • Завершить имена методов с помощью Test
  • Начать имена методов с имени класса

7 ответов

Решение

Я в значительной степени с тобой в этом одном человеке. Соглашения об именах, которые вы использовали:

  • Понятно, что такое каждое тестовое состояние.
  • Конкретно об ожидаемом поведении.

Что еще нужно от имени теста?

Вопреки ответу Рэя, я не думаю, что префикс Test необходим. Это тестовый код, мы это знаем. Если вам нужно сделать это, чтобы идентифицировать код, тогда у вас есть большие проблемы, ваш тестовый код не должен смешиваться с вашим рабочим кодом.

Что касается длины и использования подчеркивания, его тестового кода, кого это волнует? Только вы и ваша команда увидите это, пока оно читаемо и понятно о том, что делает тест, продолжайте!:)

Тем не менее, я все еще новичок в тестировании и ведении блогов своих приключений с ним:)

Это также стоит прочитать: Структурирование модульных тестов

Структура имеет тестовый класс для каждого тестируемого класса. Это не так необычно. Но для меня было необычным то, что у него был вложенный класс для каждого тестируемого метода.

например

using Xunit;

public class TitleizerFacts
{
    public class TheTitleizerMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void Name_AppendsTitle()
        {
            // Test code
        }
    }

    public class TheKnightifyMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void MaleNames_AppendsSir()
        {
            // Test code
        }

        [Fact]
        public void FemaleNames_AppendsDame()
        {
            // Test code
        }
    }
}

И вот почему:

Ну, во-первых, это хороший способ организовывать тесты. Все тесты (или факты) для метода сгруппированы вместе. Например, если вы используете сочетания клавиш CTRL+M, CTRL+O, чтобы свернуть тела методов, вы можете легко сканировать свои тесты и читать их как спецификации для своего кода.

Мне также нравится этот подход:

MethodName_StateUnderTest_ExpectedBehavior

Так что, возможно, приспособиться к:

StateUnderTest_ExpectedBehavior

Потому что каждый тест уже будет во вложенном классе

Я склонен использовать соглашение MethodName_DoesWhat_WhenTheseConditions так например:

Sum_ThrowsException_WhenNegativeNumberAs1stParam

Тем не менее, я вижу, что название теста должно соответствовать структуре модульного тестирования:

  • организовать
  • акт
  • утверждать

Что также соответствует синтаксису BDD / Gherkin:

  • Дано
  • когда
  • затем

который будет называть тест в виде: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

Итак, к вашему примеру:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

Однако я предпочитаю сначала ставить проверяемое имя метода, потому что тогда тесты можно расположить в алфавитном порядке или отсортировать по алфавиту в выпадающем списке элементов в VisStudio, и все тесты для одного метода сгруппированы вместе.


В любом случае, мне нравится разделять основные разделы имени теста подчеркиванием, а не каждым словом, потому что я думаю, что это облегчает чтение и понимание сути теста.

Другими словами, мне нравится: Sum_ThrowsException_WhenNegativeNumberAs1stParam лучше чем Sum_Throws_Exception_When_Negative_Number_As_1st_Param,

Я называю свои методы тестирования, как и другие методы, используя "PascalCasing" без подчеркивания или разделителей. Я оставляю постфиксный Test для метода, потому что он не добавляет никакой ценности. То, что метод является тестовым, указывается атрибутом TestMethod.

[TestMethod]
public void CanCountAllItems() {
  // Test the total count of items in collection.
}

В связи с тем, что каждый класс Test должен проверять только один другой класс, я оставляю имя класса вне имени метода. Имя класса, содержащего тестовые методы, именуется как тестируемый класс с постфиксом "Тесты".

[TestClass]
public class SuperCollectionTests(){
    // Any test methods that test the class SuperCollection
}

Для методов, которые проверяют исключения или действия, которые невозможны, я ставлю префикс метода теста со словом Cannot.

[TestMethod]
[ExpectedException(typeOf(ArgumentException))]
public void CannotAddSameObjectAgain() {
  // Cannot add the same object again to the collection.
}

Мое соглашение об именах основано на статье Брайана Кука "Советы TDD: тестовые соглашения об именах и руководящие указания". Я нашел эту статью очень полезной.

Первый набор имен для меня более читабелен, так как CamelCasing разделяет слова и нижние черты - отдельные части схемы именования.

Я также склоняюсь включать "Test" где-нибудь, либо в имя функции, либо в пространство имен или класс.

Пока вы следуете одной практике, это не имеет большого значения. Как правило, я пишу один модульный тест для метода, который охватывает все варианты метода (у меня есть простые методы;), а затем пишу более сложные наборы тестов для методов, которые требуют этого. Моя структура именования, таким образом, обычно тестовая (пережиток JUnit 3).

Я использую префикс 'T' для тестовых пространств имен, классов и методов.

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

AProj
   Objects
      AnObj
         AProp
   Misc
      Functions
         AFunc
   Tests
      TObjects
         TAnObj
            TAnObjsAreEqualUnderCondition
      TMisc
         TFunctions
            TFuncBehavesUnderCondition

Я легко вижу, что что-то является тестом, я точно знаю, к какому оригинальному коду это относится, (если вы не можете решить это, тогда тест все равно слишком запутан).

Это выглядит так же, как соглашение об именах интерфейсов (я имею в виду, что вы не путаетесь с вещами, начинающимися с "I", и не будете с "T").

Легко просто скомпилировать с тестами или без них.

В любом случае, это хорошо в теории, и хорошо работает для небольших проектов.

Другие вопросы по тегам