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

Общий

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

Примеры

1) имя_метода_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.
  • Начинайте имена методов с имени класса

person Community    schedule 18.09.2008    source источник
comment
См. Разработка, основанная на поведении.   -  person Wedge    schedule 19.09.2008


Ответы (7)


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

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

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

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

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

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

person Rob Cooper    schedule 18.09.2008
comment
Небольшое противоречие, если оно читабельно, ясно и кого это… волнует. Ну, всех волнует, когда это не читается и не ясно, вот почему это важно. :-) - person David Victor; 31.05.2012
comment
Один дополнительный аргумент для префикса. Когда вы ищете файл в IDE, вы можете легко искать тестовые примеры, начав с Test и имени вашего класса. Если имя класса и имя тестового класса совпадают, нам всегда придется делать паузу и читать путь к двум файлам. - person THIS USER NEEDS HELP; 12.01.2018
comment
@THISUSERNEEDSHELP Я думаю, что ваша точка зрения может быть легко преодолена с помощью хорошей структуры папок, такой как src/libs и src/tests . Я знаю, что некоторые среды выполнения тестов требуют префикса, такого как test, для идентификации тестового кода, поэтому в этих случаях этого нельзя избежать, но в остальных случаях это может быть повторяющийся не требуется< /i> префикс. - person negrotico19; 30.01.2019
comment
@ negrotico19 Я имею в виду случай, как в IntelliJ, когда вы Search Everywhere (переключение сдвига) или Find a Class By Name (CMD O). Я понимаю, что он будет различаться структурой папок или структурой модулей, но когда мы что-то ищем, мы уже знаем, что мы хотим искать. Например, если я ищу тест, я хочу ограничить свой поиск до test, а затем искать имя, а не искать имя и затем отфильтровывать тест вручную глазами. Это небольшая разница, но гораздо проще протестировать [имя класса] и получить только одно всплывающее окно, что снизит умственную нагрузку. - person THIS USER NEEDS HELP; 31.01.2019

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

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

e.g.

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

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

person Community    schedule 21.01.2012
comment
Для тех, кто использует средство запуска тестов Resharper в Visual Studio, они исправили ошибки, используя вложенные тестовые классы в 8.x. С тех пор это стало моей предпочтительной структурой на сегодняшний день. - person angularsen; 11.03.2015
comment
Имеет ли значение, что имя становится очень длинным с подходом MethodName_StateUnderTest_ExpectedBehavior? Например, InitializeApiConfiguration_MissingApiKey_IllegalArgumentException. Это действительно хорошее имя для теста? - person portfoliobuilder; 21.06.2019

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

Sum_ThrowsException_WhenNegativeNumberAs1stParam

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

  • Договариваться
  • Действовать
  • Утверждать

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

  • Дано
  • Когда
  • Затем

что означало бы назвать тест следующим образом: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

так что к вашему примеру:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

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


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

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

person Community    schedule 15.02.2012

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

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

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

[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: соглашения об именах тестов" & Руководства" Брайана Кука. Я нашел эту статью очень полезной.

person Community    schedule 18.08.2009
comment
+1 за ссылку на мой пост - хотя нет необходимости использовать префикс Test в ваших тестах. Убедитесь, что ваши тесты определяют ожидаемое поведение. Например, CanRetrieveProperCountWhenAddingMultipleItems() - person bryanbcook; 02.09.2009
comment
Мне это не нравится, потому что это не включает ожидаемое поведение - person Johannes Rudolph; 03.09.2009

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

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

person Frank Szczerba    schedule 18.09.2008
comment
@Frank имя_метода = camelCase имя_метода = PascalCase - person Metro Smurf; 14.06.2009
comment
@metro-smurf: интересное различие, я никогда не слышал, чтобы использовался термин PascalCase, а я уже давно этим занимаюсь. Я вижу, что термин PascalCase появляется только в кругах разработчиков Microsoft, это то, чем вы занимаетесь? - person Frank Szczerba; 19.06.2009
comment
История Pascal Casing и Camel Casing (от: Brad Abrams — блоги .msdn.com/brada/archive/2004/02/03/67024.aspx )... При первоначальном проектировании Framework у нас были сотни часов споров о стиле именования. Чтобы облегчить эти дебаты, мы придумали ряд терминов. Поскольку Андерс Хейлсберг (первоначальный разработчик Turbo Pascal) был ключевым членом команды разработчиков, неудивительно, что мы выбрали термин Pascal Casing для стиля корпуса, популяризированного языком программирования Pascal. - person Riegardt Steyn; 05.02.2013

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

person Munger    schedule 18.09.2008

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

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

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

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

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

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

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

person Community    schedule 07.01.2011
comment
Интересный подход. Некоторые люди могут возразить, что префикс T противоречит соглашению, которое вы используете в дженериках (например, func(T1, T2, TResult)), но меня лично это не волнует, пока внутри команды есть консенсус. Имена короткие, что делает вещи более читабельными. - person stung; 11.01.2011
comment
Слишком венгерский (обозначение) для меня. Кроме того, как было сказано в рекламе, префикс T используется для параметров универсального типа. - person Danny Varod; 21.06.2011
comment
Я согласен, венгерская нотация устарела, и из-за конфликта со стандартными параметрами универсального типа я не вижу применения исключения в этом случае (как для интерфейсов). - person SonOfPirate; 13.12.2011