Стандарты кодирования модульного тестирования
https://softwareengineering.stackexchange.com/questions/15925
-
22-10-2019 - |
Вопрос
Обычно, когда говорим о стандартах кодирования, мы ссылаемся на код самой программы, но как насчет модульных тестов? Существуют ли определенные рекомендации по стандартам кодирования, которые уникальны для модульных тестов? Кто они такие?
Решение
В верхней части моей головы я могу вспомнить три различия в стиле кодирования для тестового кода.
В методах испытаний на наименование я следую за шаблоном shouldDoSomethingWhenSomeConditionHolds
.
Внутри теста обычно следовать следующему шаблону интервалов:
@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
// Some lines
// of setup code
// go here.
// The action being tested happens after a blank line.
// An assertion follows another blank line.
}
Некоторые настаивают только на одном утверждении за тест, но это далеко не универсально.
Сухой (не повторяйся) - это меньше учета в тестовом коде, чем в производственном коде. В то время как какой -то повторяющийся код должен быть размещен в методе настройки или в классе Testutils, стремление к нулевому повторению в тестовом коде приведет к жестко связанным и негибким тестам, что препятствует рефакторинге.
Другие советы
Рой Осгероув рекомендует следующую шаблон для названия ваших тестов:
NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior()
Видеть http://weblogs.asp.net/rosherove/archive/2005/04/03/testnamingstandards.aspx
Главное, чтобы помнить, что модульные тесты по сути являются мини-спецификацией. Это означает, что акцент всегда должен быть на читабельности.
Во -первых, это означает, что имена должны четко сообщать о том, что находится под тестированием, и что утверждается.
Во -вторых, что иногда забывается, заключается в том, что в качестве спецификаций они должны делать именно это - определение поведения. То есть модульные тесты не должны содержать логику - или, возможно, они попадают в ловушку повторять функциональность программы, а не тестировать ее.
Иногда тесты будут включать объекты, которые являются сложными для настройки, вы должны стремиться сохранить эту логику настройки от ваших тестов, используя что -то вроде объект мать или Проверка данных Строитель.
Я просто завершу несколько рекомендаций книги:
Тестовые шаблоны XUNIT: рефакторинг кода тестирования: Отличная книга, некоторые говорят, что это немного сухо, но я так не думаю. Вдается много деталей о множестве различных способов организации тестов и о том, как сохранить их поддержание. Актуально, если вы используете что -то вроде NUNIT и т. Д.
Искусство модульного тестирования: с примерами в .net: Лучшая книга о том, что он сбит с ума по написанию и поддержанию тестов. Несмотря на то, что я действительно новичок, я нахожу насмешливые секции уже немного устаревшими, поскольку синтаксис AAA теперь довольно стандартный, а не просто еще один способ сделать это.
Растущее объектно-ориентированное программное обеспечение, руководствовавшимся тестами: Эта книга просто потрясающая! Безусловно, самая лучшая книга для тестирования модуля и единственная продвинутая, которая проводит модульные тестирование в качестве гражданина первоклассного в процессе проектирования. Читал это, когда это была публичная бета -версия, и с тех пор рекомендовал. Отличный реальный проработанный пример, используемый на протяжении всей книги. Рекомендую сначала прочитать книгу Роя.
Не ставьте логику в свои модульные тесты. Например, допустим, вы тестируете метод добавления, у вас может быть что -то вроде этого:
void MyTest_SaysHello()
{
string name = "Bob";
string expected = string.Format("Hello, {0}", name);
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello(name);
Assert.AreEqual(expected, actual);
}
В этом конкретном случае вы, вероятно, повторяете ту же логику, что и в тесте, поэтому вы по сути тестируете «1 + 1 == 1 + 1», а не «1 + 1 == 2», который является «Настоящий» тест. Так что вы бы действительно хотели, чтобы ваш тестовый код выглядел:
void MyTest_SaysHello()
{
string expected = "Hello, Bob";
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello("Bob");
Assert.AreEqual(expected, actual);
}
Длинные, описательные имена методов. Помните, что методы испытаний никогда не вызываются из кода (их называют модульным тестовым бегуном, который обнаруживает и вызывает их с помощью отражения), поэтому можно сходить с ума и иметь имена методов 50-80 символов. Конкретное соглашение об именах (верблюжье, подчеркивание, «должно», «должно», «когда», «дается» и т. Д.) Не очень важна, если имя отвечает на три вопроса:
- Что находится под тестированием?
- Какие условия?
- Каков ожидаемый результат?
Методы испытаний должны быть короткими.
Методы испытаний должны иметь Простая линейная структура. Анкет Нет, если или петля конструкции.
Методы испытаний должны следовать Узор "Arrange-Act-Assert".
Каждый тест должен Проверьте одну вещь. Анкет Обычно это означает одно утверждение за тест. Тест как { Do A; Assert B; Assert C; }
должно быть переработано на два: { Do A; Assert B; }
а также { Do A; Assert C; }
Избегайте случайных данных или такие вещи, как 'datetime.now'
Убедитесь, что все участники тестового матча возвращаются в свое первоначальное состояние в конце теста (например, с помощью срывать)
Даже если вы безжалостно устраняете дублирование в своем производственном коде, дублирование кода в тестовых приспособлениях гораздо меньше.
Несколько похоже на то, что уже упомянул Farmboy, формат названия моего метода
<MethodName>Should<actionPerformed>When<Condition>
например
GetBalanceShouldReturnAccountBalance() {