Написание стандартов для модульного тестирования - PullRequest
11 голосов
/ 03 февраля 2009

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

Эти два поста ( Рекомендации по именованию модульных тестов и Рекомендации по зависимостям файловой системы при тестировании модулей / интеграций ) уже дали мне пищу для размышлений.

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

Есть что-нибудь еще для включения?

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

РЕДАКТИРОВАТЬ: я использую Visual Studio Team System 2008 и я разрабатываю на C # .Net

Ответы [ 10 ]

9 голосов
/ 03 февраля 2009

Взгляните на Michael Feathers о том, что такое юнит-тест (или что делает юнит-тесты плохими юнит-тестами)

Взгляните на идею "Arrange, Act, Assert", то есть идею, что тест выполняет только три вещи в фиксированном порядке:

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

Взгляните на Behavior Driven Development , чтобы найти способ согласования тестовых случаев с требованиями.

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

7 голосов
/ 03 февраля 2009

Возможно, вам стоит взглянуть на серию "Прагматическое модульное тестирование". Это версия C #, но есть и другая для Java.

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

Обновление: я не согласен с Мистером Картофельным Хэдом насчет только одного утверждения за юнит-тест. Это звучит довольно хорошо в теории, но на практике это приводит либо к большому количеству в основном избыточных тестов, либо к людям, выполняющим тонны работы по настройке и демонтажу, которые должны быть проверены * .

5 голосов
/ 04 февраля 2009

Я придерживаюсь стиля BDD TDD. Увидеть: http://blog.daveastels.com/files/BDD_Intro.pdf http://dannorth.net/introducing-bdd http://behaviour -driven.org / Введение

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

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

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

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

Некоторое время назад я написал учебник по TDD (где вы начинаете писать игру Tetris с использованием предоставленных тестов), в которой этот стиль написания тестов представлен в виде спецификаций. Вы можете скачать его с 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 и т.д.

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

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

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

1 голос
/ 13 марта 2009

Не забудьте включить то, что не является модульным тестом. См .: Что не нужно тестировать, когда дело доходит до модульного тестирования?

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

Проверьте это для получения дополнительной информации: Как я могу улучшить свои тесты Junit ... особенно второе обновление.

1 голос
/ 03 февраля 2009

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

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

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

1 голос
/ 03 февраля 2009

Пользователи полнофункциональных 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 голос
/ 03 февраля 2009

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

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

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

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

0 голосов
/ 03 февраля 2009

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

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

...