Каковы некоторые популярные соглашения об именовании для модульных тестов?[закрыто]
-
01-07-2019 - |
Вопрос
Общая информация
- Соблюдайте одни и те же стандарты для всех тестов.
- Четко представляйте, что представляет собой каждое тестовое состояние.
- Будьте конкретны в отношении ожидаемого поведения.
Примеры
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 ()
Другое
- Завершать имена методов с помощью Тест
- Начинайте имена методов с имени класса
Решение
Я в значительной степени согласен с вами в этом вопросе, мужчина.Соглашения об именовании, которые вы использовали, следующие:
- Четко определите, что представляет собой каждое тестовое состояние.
- Конкретно об ожидаемом поведении.
Что еще вам нужно от тестового имени?
Вопреки Ответ Рэя Я не думаю, что Тест префикс необходим.Это тестовый код, мы это знаем.Если вам нужно сделать это для идентификации кода, то у вас возникают более серьезные проблемы, ваш тестовый код не должен быть перепутан с вашим производственным кодом.
Что касается длины и использования подчеркивания, то его тестовый код, - кого это, черт возьми, волнует?Только вы и ваша команда увидите это, пока оно читабельно и дает четкое представление о том, что делает тест, продолжайте!:)
Тем не менее, я все еще новичок в тестировании и веду блог о своих приключениях с ним :)
Другие советы
Это тоже стоит прочитать: Структурирование модульных тестов
Структура имеет тестовый класс для каждого тестируемого класса.В этом нет ничего необычного.Но что было необычным для меня, так это то, что у него был вложенный класс для каждого тестируемого метода.
например ,
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
Так что, возможно, приспособитесь к:
Состояние в соответствии с тестом_expectedbehavior
Потому что каждый тест уже будет находиться во вложенном классе
Я склонен использовать соглашение о MethodName_DoesWhat_WhenTheseConditions
так, например:
Sum_ThrowsException_WhenNegativeNumberAs1stParam
Однако, что я действительно вижу во многом, так это то, чтобы название теста соответствовало структуре модульного тестирования
- Организовать
- Действовать
- Утверждать
Который также следует синтаксису BDD / Gherkin для:
- Данный
- Когда
- Тогда
который состоял бы в том, чтобы назвать тест следующим образом: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis
итак, к вашему примеру:
WhenNegativeNumberAs1stParam_Sum_ThrowsAnException
Однако я предпочитаю сначала указывать имя тестируемого метода, потому что тогда тесты могут быть расположены в алфавитном порядке или отображаться отсортированными по алфавиту в раскрывающемся списке member в VisStudio, и все тесты для 1 метода группируются вместе.
В любом случае, мне нравится разделять основные разделы имени теста с подчеркиванием, в отличие от каждого слово, потому что я думаю, что так легче читать и донести суть теста.
Другими словами, мне нравится: Sum_ThrowsException_WhenNegativeNumberAs1stParam
лучше, чем Sum_Throws_Exception_When_Negative_Number_As_1st_Param
.
Я называю свои методы тестирования, как и другие методы, используя "PascalCasing" без каких-либо подчеркиваний или разделителей.Я оставляю постфикс Тест для метода out, потому что он не добавляет никакой ценности.На то, что метод является тестовым, указывает атрибут Метод тестирования.
[TestMethod]
public void CanCountAllItems() {
// Test the total count of items in collection.
}
В связи с тем, что каждый тестовый класс должен тестировать только один другой класс, я исключаю имя класса из имени метода.Имя класса, содержащего тестовые методы, называется так же, как и тестируемый класс, с постфиксом "Tests".
[TestClass]
public class SuperCollectionTests(){
// Any test methods that test the class SuperCollection
}
Для методов, которые проверяют наличие исключений или действий, которые невозможны, я добавляю к методу тестирования слово Не могу.
[TestMethod]
[ExpectedException(typeOf(ArgumentException))]
public void CannotAddSameObjectAgain() {
// Cannot add the same object again to the collection.
}
Мои правила именования основаны на этой статье "Советы по TDD:Соглашения об именовании тестов и рекомендации" о Брайане Куке.Я нашел эту статью очень полезной.
Первый набор имен для меня более удобочитаем, поскольку надпись camelCasing разделяет слова, а нижние панели - отдельные части схемы именования.
Я также склонен включать "Test" где-нибудь, либо в имя функции, либо в окружающее пространство имен или класс.
Пока вы придерживаетесь какой-то одной практики, это на самом деле не имеет значения.Как правило, я пишу единый модульный тест для метода, который охватывает все варианты метода (у меня есть простые методы;), а затем пишу более сложные наборы тестов для методов, которые этого требуют.Таким образом, моя структура именования обычно является тестовой (пережиток JUnit 3).
Я использую префикс "T" для тестовых пространств имен, классов и методов.
Я стараюсь быть аккуратным и создаю папки, которые реплицируют пространства имен, затем создаю папку tests или отдельный проект для тестов и реплицирую производственную структуру для базовых тестов:
AProj
Objects
AnObj
AProp
Misc
Functions
AFunc
Tests
TObjects
TAnObj
TAnObjsAreEqualUnderCondition
TMisc
TFunctions
TFuncBehavesUnderCondition
Я легко вижу, что что-то является тестом, я точно знаю, к какому исходному коду это относится (если вы не можете с этим разобраться, то тест в любом случае слишком запутанный).
Это выглядит точно так же, как соглашение об именовании интерфейсов (я имею в виду, вас не запутают вещи, начинающиеся на "I", и вы не запутаетесь с "T").
Легко просто скомпилировать с тестами или без них.
В любом случае, это хорошо в теории и довольно хорошо работает для небольших проектов.