2009-02-03 3 views
10

Я планирую ввести набор стандартов для написания модульных тестов в моей команде. Но что включать?Стандарты написания для модульных испытаний

Эти две должности (Unit test naming best practices и Best practices for file system dependencies in unit/integration tests) дали мне немного еды для размышлений.

Другие домены, которые должны быть охвачены в моих стандартах, должны заключаться в том, как настраиваются тестовые классы и как их организовать. Например, если у вас есть класс под названием OrderLineProcessor, должен быть класс проверки, называемый OrderLineProcessorTest. Если в этом классе есть метод, называемый Process(), тогда должен быть тест под названием ProcessTest (возможно, больше для тестирования разных состояний).

Любые другие вещи для включения?

Имеет ли ваша компания стандарты для модульных испытаний?

EDIT: Я использую Visual Studio Team System 2008 и я развиваю в C# .Net

+0

@ Gerrie просто добавил ответ на этот старый вопрос, проверьте его – eglasius

ответ

9

Посмотрите Michael Feathers on what is a unit test (или то, что делает юнит тесты плохие тесты блок)

взглянуть на идею «Arrange, Закон, Утверждай», то есть идея о том, что тест делает только три вещи, в фиксированный порядок:

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

Посмотрите на Behaviour Driven Development, чтобы выровнять тестовые примеры с требованиями.

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

7

Вы, вероятно, следует взглянуть на серию "Прагматический Unit Testing". This - это версия C#, но для Java есть другая.

Что касается вашей спецификации, я бы не go overboard. У вас очень хорошее начало - соглашения об именах очень важны. Мы также требуем, чтобы структура каталогов соответствовала исходному проекту. Охват также должен распространяться на граничные случаи и незаконные значения (проверка на исключения). Это очевидно, но ваша спецификация - это место, где можно записать этот аргумент, который вы неизбежно будете иметь в будущем с парнем, который не хочет проверять, что кто-то пропустил незаконную ценность. Но не делайте spec более чем на нескольких страницах, или никто не будет использовать его для задачи, которая так зависит от контекста.

Обновление: Я не согласен с г-ном картофельным глазом об одном утверждении на единицу измерения. Звучит неплохо в теории, но на практике это приводит либо к нагрузкам в основном избыточных тестов, либо к людям, которые выполняют тонны работы при настройке и срыве, что должно быть проверено .

+0

Я думаю, что простой набор стандартов может легко поместиться на одной странице (без примеров). Возможно, два. –

+0

Спасибо, Джерри - моя не совсем подходит для страницы ... –

+0

Когда вы говорите, что ваш «более чем на нескольких страницах» - это 3 страницы? :) –

0

Если вы используете инструменты из семейства Junit (OCunit, SHunit, ...), имена тестов уже соответствуют некоторым правилам.

Для моих тестов я использую пользовательские теги Doxygen, чтобы собрать их документацию на определенной странице.

4
  1. Постарайтесь использовать как можно меньше утверждений утверждения для каждого метода испытаний. Это гарантирует, что цель теста будет четко определена.
  2. Я знаю, что это будет противоречиво, но не проверяйте время компилятора - время, затрачиваемое на тестирование компонентов Java Bean и мутаторов, лучше потратить на другие тесты.
  3. Попробуйте, где возможно, использовать TDD вместо написания тестов после вашего кода.
+1

1 кажется немного суровым. Предположим, я хотел проверить, что только что сконструированный Vector3 имеет все компоненты, инициализированные до нуля? Вы действительно заставили бы меня написать отдельный тест для каждого компонента или предпочесть assert (v.x() == 0.0 && v.y() == 0.0 && v.z() == 0.0) отдельному утверждению для каждого компонента? – timday

+0

Также вы не должны делать assertEquals (новый Vector3 (0.0, 0.0, 0.0), (vector)) - тест, в котором значения, переданные в конструктор, доступные из методов x(), y() и z(), должны быть сделанный кем-то из Microsoft ... –

+0

Я также нахожу (1) слишком сложно. – starblue

3

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

Я также защищаю стиль тестирования Arrange-Act-Assert (AAA), так как вы можете создать довольно полезную документацию из своих тестов. Это также заставляет вас подумать о том, какое поведение вы ожидаете из-за стиля именования.

+0

У вас есть дополнительная информация об этом стиле AAA? Любые ссылки на статьи? –

+0

Найдена ссылка для вас –

+0

очень информативная ссылка, спасибо – arturh

1

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

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

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

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

1

Пользователи полнофункциональных IDE обнаруживают, что «некоторые из них» имеют довольно подробную поддержку для создания тестов в определенном шаблоне. Учитывая этот класс:

public class MyService { 
    public String method1(){ 
     return ""; 
    } 

    public void method2(){ 

    } 

    public void method3HasAlongName(){ 

    } 
} 

При нажатии Ctrl-Shift-T в IntelliJ IDEA я получаю этот тестовый класс после ответа 1 диалогового окна:

public class MyServiceTest { 
    @Test 
    public void testMethod1() { 
     // Add your code here 
    } 

    @Test 
    public void testMethod2() { 
     // Add your code here 
    } 

    @Test 
    public void testMethod3HasAlongName() { 
     // Add your code here 
    } 
} 

Таким образом, вы можете захотеть, чтобы внимательно посмотреть на прежде чем писать ваши стандарты.

1

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

TEST(TestThatVariableFooDoesNotOverflowWhenCalledRecursively) 
{ 
/* do test */ 
} 

Я использую C++, но соглашение об именах можно использовать в любом месте.

5

Я следую стилю BDD TDD. См: http://blog.daveastels.com/files/BDD_Intro.pdf http://dannorth.net/introducing-bdd http://behaviour-driven.org/Introduction

Короче говоря, это означает, что

  • Испытание не думало, как «испытание», но так как технические характеристики поведения системы (далее называемый «спецификация»). Целью спецификаций является не проверка того, что система работает при любых обстоятельствах. Их цель - указать поведение и управлять дизайном системы.

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

  • Не существует принудительного отношения 1: 1 между производственными классами и классами спецификаций (и создание метода испытаний для каждого метода производства будет безумным). Вместо этого существует соотношение 1: 1 между поведением системы и спецификациями.

Некоторое время назад я написал TDD учебник (где вы начнете писать игру Тетрис, используя предоставленные тесты), который показывает этот стиль написания тестов, как спецификация. Вы можете загрузить его с http://www.orfjackal.net/tdd-tutorial/tdd-tutorial_2008-09-04.zip Инструкции по работе с TDD/BDD по-прежнему отсутствуют в этом учебнике, но примерный код готов, поэтому вы можете увидеть, как организованы тесты и писать код, который их передает.

Вы заметите, что в этом уроке производственные классы называются такими, как Board, Block, Piece и Tetrominoe, которые сосредоточены вокруг концепций игры Tetris. Но тестовые классы сосредоточены вокруг поведения игры Тетрис: FallingBlocksTest, RotatingPiecesOfBlocksTest, RotatingTetrominoesTest, FallingPiecesTest, MovingAFallingPieceTest, RotatingAFallingPieceTest и т.д.

1

Убедитесь, что включать то, что это не блок тестов. См.: What not to test when it comes to Unit Testing?

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

Проверьте это для получения более подробной информации: How can I improve my junit tests ... особенно второе обновление.

Смежные вопросы