Unit test документация

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

Мой опыт работы в качестве разработчика говорит мне, что понимание старого кода (включая модульные тесты) затруднено.

Итак, что важно в тестовой документации? Когда имя метода тестирования недостаточно описательно, чтобы документация была оправдана?

Ответ 1

По просьбе Thorsten79, я расскажу о своих комментариях в качестве ответа. Мой оригинальный комментарий был:

"Код говорит", к сожалению совершенно неправильно, потому что не разработчик не может прочитать код, хотя он может хотя бы частично читать и понять документации, и таким образом он может знать, что тестирует тест. Это особенно важно в тех случаях, когда клиент полностью понимает домена и просто не может читать код, и становится еще более важным, когда блок тесты также проверяют оборудование, как в встроенный мир, потому что тогда вы тестируете вещи, которые можно увидеть.

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

В смешанной аппаратной/программной разработке, например, в моей компании, клиенты знают, чего хотят. Если их полевое устройство должно выполнять reset при получении определенной команды шины, должен быть unit test, который отправляет эту команду и проверяет, было ли устройство reset. Мы делаем это здесь прямо сейчас, используя NUnit в качестве рамки unit test, и некоторые пользовательские программные и аппаратные средства, которые позволяют отправлять и получать команды (и даже нажатия кнопок). Это здорово, потому что единственной альтернативой было бы сделать все это вручную.

Клиент абсолютно хочет знать, какие тесты существуют, и он даже хочет сам запускать тесты. Если тесты не были должным образом задокументированы, он не знает, что делает тест, и не может проверить, есть ли все тесты, которые, по его мнению, ему понадобятся, и при проведении теста он не знает, что он будет делать. Потому что он не может прочитать код. Он знает, что используемая система автобусов лучше, чем наши разработчики, но они просто не могут прочитать код. Если тест терпит неудачу, он не знает, почему и не может даже сказать, что, по его мнению, должен делать тест. Это нехорошо.

Задокументировав модульные тесты правильно, мы имеем

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

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

Независимо от нашей точной ситуации, я думаю, что то, что я хочу в модульных тестах все время, даже если они являются чистым программным обеспечением. Клиент может игнорировать unit test, который ему неинтересен, например, базовые функциональные тесты. Но просто иметь документы не повредит.

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

Ответ 2

В самом тестовом коде:

  • С комментариями уровня метода, объясняющими что тест тестирует/покрывает.

  • На уровне класса комментарий, указывающий на фактический класс, который тестируется (что фактически может быть выведено из имени тестового класса, что фактически менее важно, чем комментарии на уровне метода).

С отчетами по охвату тестирования

  • Например Cobertura. Это также документация, так как она указывает, что ваши тесты покрывают, а какие нет.

Ответ 3

Комментируйте сложные тесты или сценарии, если требуется, но предпочитают читаемые тесты.

С другой стороны, я стараюсь, чтобы мои тесты говорили сами за себя. Другими словами:

[Test]
public void person_should_say_hello() {
     // Arrange.
     var person = new Person();
     // Act.
     string result = person.SayHello();
     // Assert.
    Assert.AreEqual("Hello", result, "Person did not say hello");
}

Если бы я посмотрел на этот тест, я бы увидел, что он использовал Person (хотя он был бы в PersonTest.cs в качестве подсказки;)), тогда, если что-то сломается, это произойдет в методе SayHello. Сообщение assert также полезно, а не только для чтения тестов, но при выполнении тестов легче увидеть их в графическом интерфейсе.

Следуя AAA, стиль Arrange, Act и Assert заставляет тест по существу документировать сам. Если этот тест был более сложным, вы могли бы добавить комментарии выше тестовой функции, объясняя, что происходит. Как всегда, вы должны обеспечить их постоянную актуальность.

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

public void PersonShouldSayHello()

Что для длинных имен методов может затруднить чтение теста. Хотя этот момент часто субъективен.

Ответ 4

Когда я возвращаюсь к старому тесту и не понимаю его сразу

  • Я рефакторинг, если возможно
  • или напишите этот комментарий, который заставил бы меня сразу понять это.

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

Обратите внимание, что это не значит, что я никогда не пишу никаких комментариев. Там все еще есть много ситуаций, когда я просто знаю, что мне будет сложно определить, что делает конкретный кусок кода.

Обычно я начинаю с точки 1 в этих ситуациях...

Ответ 5

Улучшение модульных тестов в качестве исполняемой спецификации - это точка Поведенческая разработка: BDD - это эволюция TDD, в которой используются модульные тесты Вездесущий язык (язык, основанный на бизнес-домене и разделяемый разработчиками и заинтересованными сторонами) и выразительные имена (testCannotCreateDuplicateEntry), чтобы описать, что код должен делать. Некоторые рамки BDD очень сильно продвинули идею и продемонстрировали исполняемый файл, написанный с почти естественным языком, для пример.

Ответ 6

Я бы советовал какой-либо подробной документации отдельно от кода. Зачем? Потому что всякий раз, когда вам это нужно, он, скорее всего, будет очень устаревшим. Лучшим местом для детальной документации является сам код (включая комментарии). BTW, все, что вам нужно сказать о конкретном unit test, - это очень подробная документация.

Несколько указателей на то, как достичь хорошо самодокументированных тестов:

  • Следуйте стандартным способам написания всех тестов, например шаблон AAA. Используйте пустую строку для разделения каждой части. Это позволяет читателю легче идентифицировать важные биты.
  • Вы должны включить в каждое тестовое имя: тестируемое, текущую ситуацию и ожидаемое поведение. Например: test__getAccountBalance__NullAccount__raisesNullArgumentException()

  • Извлеките общую логику в методы настройки/удаления или вспомогательные методы с описательными именами.

  • По возможности используйте образцы из реальных данных для входных значений. Это гораздо более информативно, чем пустые объекты или составлены JSON.
  • Использовать переменные с описательными именами.
  • Подумайте о своем будущем вы/товарищ по команде, если вы ничего не вспомнили об этом, хотите ли вы получить какую-либо дополнительную информацию, если тест не удастся? Напишите это как комментарии.

И чтобы дополнить другие ответы:

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

  • Ед. тесты должны охватывать определенные единицы кода (методы/функции в классах/модулях), если вы охватите больше земли, они быстро превратятся в интеграционные тесты, которые тоже нужны и нужны, но если вы не отдельно отделяйте их, люди просто путают их, и вы потеряете некоторые преимущества модульного тестирования. Например, когда сбой unit test вы должны получить мгновенное обнаружение ошибок (особенно, если вы следуете вышеприведенному соглашению об именах). Когда тест интеграции завершается неудачно, вы знаете, что есть проблема, и вы знаете некоторые из ее эффектов, но вам может потребоваться отладка, иногда в течение длительного времени, чтобы найти, что это такое.

  • Вы можете использовать модульные модули тестирования для тестов интеграции, если хотите, но вы должны знать, что вы не выполняете модульное тестирование, и вы должны хранить их в отдельных файлах/каталогах.

  • Существуют хорошие рамки для тестирования приёма/поведения (FitNesse, Robot, Selenium, Cucumber и т.д.), которые могут помочь не только читать, но и сами тесты. Конечно, им понадобится помощь от кодеров, чтобы заставить их работать (особенно при запуске), но они смогут это сделать, и им не нужно ничего знать о ваших модулях или классах функций.