Каковы некоторые популярные соглашения об именах для модульных тестов?
генеральный
- Следуйте одинаковым стандартам для всех тестов.
- Проясните, что такое каждое тестовое состояние.
- Будьте конкретны в отношении ожидаемого поведения.
Примеры
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").
Легко просто скомпилировать с тестами или без них.
В любом случае, это хорошо в теории, и хорошо работает для небольших проектов.