Как глубоко Ваши модульные тесты?

takeWhile является одной из функций, предоставляемых библиотекой protonpack .

Stream infiniteInts = Stream.iterate(0, i -> i + 1);
Stream finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);

assertThat(finiteInts.collect(Collectors.toList()),
           hasSize(10));

88
задан Mihai Limbășan 18 October 2008 в 20:43
поделиться

17 ответов

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

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

221
ответ дан Kent Beck 5 November 2019 в 14:39
поделиться

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

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

, Если Ваш метод считывания когда-нибудь становится нетривиальным, можно все еще добавить тест для него затем.

0
ответ дан 5 November 2019 в 14:39
поделиться

Я думаю, что необходимо протестировать все в "ядре" бизнес-логики. Метод set ответа метода get также, потому что они могли принять отрицательную величину или нулевое значение, которое Вы могли бы сделать не, хочет принять. Если у Вас есть время (всегда зависят Вашего босса), хорошо протестировать другую бизнес-логику и весь контроллер, которые звонят, они возражают (Вы медленно идете от модульного теста до интеграционного теста).

0
ответ дан Patrick Desjardins 5 November 2019 в 14:39
поделиться

Я не делаю модульных тестов простой метод set/методы получателя, которые не имеют никаких побочных эффектов. Но я делаю модульный тест любой открытый метод. Я пытаюсь создать тесты для всех граничных условий в моем algorthims и проверить покрытие моих модульных тестов.

Его большая работа, но я думаю его стоящий того. Я записал бы код (даже тестирующий код), чем шаг через код в отладчике. Я нахожу code-build-deploy-debug цикл очень трудоемким и чем более исчерпывающий модульные тесты, которые я интегрировал в свою сборку, тем меньше времени я провожу прохождение через этого code-build-deploy-debug цикл.

Вы не сказали, почему архитектура Вы кодируете также. Но для Java я использую Знаток 2 , JUnit, DbUnit, Cobertura, & EasyMock.

0
ответ дан Brian Matthews 5 November 2019 в 14:39
поделиться

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

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

0
ответ дан Tim Sullivan 5 November 2019 в 14:39
поделиться

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

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

1
ответ дан Johnno Nolan 5 November 2019 в 14:39
поделиться

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

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

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

Так, Нет - я сказал бы, что нет такой вещи как "слишком много" тестирования в общем смысле, только для людей.

4
ответ дан Fry 5 November 2019 в 14:39
поделиться

Я делаю модульный тест для достижения максимального выполнимого покрытия. Если я не могу достигнуть некоторого кода, я осуществляю рефакторинг, пока покрытие не максимально полно

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

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

1
ответ дан Lorenzo Boccaccia 5 November 2019 в 14:39
поделиться

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

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

5
ответ дан itsmatt 5 November 2019 в 14:39
поделиться

Часть проблемы с пропуском простых тестов теперь находится в будущем рефакторинге, мог сделать то простое свойство очень сложным с большой логикой. Я думаю, что лучшая идея состоит в том, что можно использовать Тесты для проверки требований для модуля. Если, когда Вы передаете X, необходимо вернуть Y, то это - то, что Вы хотите протестировать. Тогда при изменении кода позже можно проверить, что X дает Вам Y, и можно добавить, что тест для A дает Вам B, когда то требование добавляется позже.

я нашел, что время трачу во время начального развития, списывающего тестовые платежи в первом или втором исправлении ошибки. Способность взять код, на который Вы не посмотрели за 3 месяца и быть довольно уверенными Ваша фиксация, покрывает все случаи, и "вероятно" не повреждается, что-либо чрезвычайно ценно. Вы также найдете, что модульные тесты помогут сортировать ошибки далеко за пределами отслеживания стека и т.д. Наблюдение, как отдельные части работы приложения и сбоя дают огромное понимание, почему они работают или перестали работать в целом.

5
ответ дан Matt 5 November 2019 в 14:39
поделиться

Классический ответ является "тестом что-либо, что могло возможно повредиться". Я интерпретирую это как то, чтобы подразумевать, что тестирование методов set и методов get, которые не делают ничего кроме набора или добираются, вероятно, очень тестирует, никакая потребность занять время. Если Ваш IDE не пишет тем для Вас, тогда Вы могли бы также.

, Если Ваш конструктор не свойства установки могли бы привести к ошибкам позже, то тестирование этого они установлены, не излишество.

9
ответ дан Dennis S. 5 November 2019 в 14:39
поделиться

Все должно быть сделано максимально простым, но не более простое. - A. Эйнштейнов

Одной из самых недооцененных вещей о TDD является первое слово в нем. Тест. Вот почему BDD пришел. Поскольку люди действительно не поняли, что первый D был важным, а именно, Управляемым. Все мы склонны думать немного к очень о Тестировании, и немного к мало об управлении дизайна. И я предполагаю, что это - неопределенный ответ на Ваш вопрос, но необходимо, вероятно, рассмотреть, как управлять кодом, вместо того, что Вы на самом деле тестируете; это - что-то, с чем инструмент Покрытия может помочь Вам. Дизайн является вполне большей и более проблематичной проблемой.

19
ответ дан kitofr 5 November 2019 в 14:39
поделиться

Разработка через тестирование означает, что Вы прекращаете кодировать, когда все Ваши тесты передают.

, Если у Вас нет теста для свойства, тогда почему необходимо реализовать его? Если Вы не тестируете/определяете ожидаемое поведение в случае "недопустимого" присвоения, что должно сделать свойство?

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

Для создания этого тестирования легче я создал простой NUnit TestFixture, который обеспечивает точки расширения для установки/получения значения и берет списки допустимых и недопустимых значений и имеет единственный тест, чтобы проверить, работает ли свойство правильно. Тестирование единственного свойства могло быть похожим на это:

[TestFixture]
public class Test_MyObject_SomeProperty : PropertyTest<int>
{

    private MyObject obj = null;

    public override void SetUp() { obj = new MyObject(); }
    public override void TearDown() { obj = null; }

    public override int Get() { return obj.SomeProperty; }
    public override Set(int value) { obj.SomeProperty = value; }

    public override IEnumerable<int> SomeValidValues() { return new List() { 1,3,5,7 }; }
    public override IEnumerable<int> SomeInvalidValues() { return new List() { 2,4,6 }; }

}

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

P.S.: Вероятно, PropertyTest должен также иметь способ проверить, что другой свойства на объекте не изменились. Хм.. назад к исходной точке.

3
ответ дан David Schmitt 5 November 2019 в 14:39
поделиться

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

  1. ошибка исправлена;
  2. ошибка не вновь появится.

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

20
ответ дан Dominic Rodger 5 November 2019 в 14:39
поделиться

При условии, что элементы переопределяют ToString соответственно:

public void WriteToConsole(IEnumerable items)
{
    foreach (object o in items)
    {
        Console.WriteLine(o);
    }
}

(Там не будет никакого преимущества в используя дженерики в этом цикле - мы в конечном итоге вызовем Console.WriteLine (object) в любом случае, так что он будет по-прежнему такой же, как и в части foreach в этом случае.)

РЕДАКТИРОВАТЬ: ответы с использованием List .ForEach очень хороши.

Мой цикл выше более гибок в случае, когда у вас есть произвольная последовательность (например, в результате LINQ выражение), но если у вас определенно есть List , я бы сказал, что List .ForEach - лучший вариант.

Одно преимущество Список .ForEach заключается в том, что если у вас есть конкретный тип списка, он будет использовать наиболее подходящую перегрузку. Например:

List<int> integers = new List<int> { 1, 2, 3 };
List<string> strings = new List<string> { "a", "b", "c" };

integers.ForEach(Console.WriteLine);
strings.ForEach(Console.WriteLine);

При записи целых чисел будет использоваться Console.WriteLine (int) , тогда как при записи строк будет использоваться Console.WriteLine (string) . Если конкретная перегрузка недоступна (или если вы просто используете общий список List и компилятор не знает, что такое T ), он будет использовать консоль .WriteLine (object) .

Обратите внимание на использование Console.WriteLine в качестве группы методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

это будет использовать Console.WriteLine (int) , тогда как при записи строк он будет использовать Console.WriteLine (string) . Если конкретная перегрузка недоступна (или если вы просто используете общий список List и компилятор не знает, что такое T ), он будет использовать консоль .WriteLine (object) .

Обратите внимание на использование Console.WriteLine в качестве группы методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

это будет использовать Console.WriteLine (int) , тогда как при записи строк он будет использовать Console.WriteLine (string) . Если конкретная перегрузка недоступна (или если вы просто используете общий список List и компилятор не знает, что такое T ), он будет использовать консоль .WriteLine (object) .

Обратите внимание на использование Console.WriteLine в качестве группы методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

тогда как при записи строк он будет использовать Console.WriteLine (string) . Если конкретная перегрузка недоступна (или если вы просто используете общий список List и компилятор не знает, что такое T ), он будет использовать консоль .WriteLine (object) .

Обратите внимание на использование Console.WriteLine в качестве группы методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

тогда как при записи строк он будет использовать Console.WriteLine (string) . Если конкретная перегрузка недоступна (или если вы просто используете общий список List и компилятор не знает, что такое T ), он будет использовать консоль .WriteLine (object) .

Обратите внимание на использование Console.WriteLine в качестве группы методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

T> и компилятор не знает, что такое T ), он будет использовать Console.WriteLine (object) .

Обратите внимание на использование Console. Кстати, WriteLine как группа методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

T> и компилятор не знает, что такое T ), он будет использовать Console.WriteLine (object) .

Обратите внимание на использование Console. Кстати, WriteLine как группа методов. Это более сжато, чем использование лямбда-выражения, и на самом деле немного более эффективно (поскольку делегат просто будет вызовом Console.WriteLine , а не вызов метода, который, в свою очередь, просто вызывает Console.WriteLine ).

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

15
ответ дан 24 November 2019 в 07:23
поделиться

Протестируйте исходный код, который вас беспокоит.

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

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

Тестируйте непонятные части кода, чтобы получить знания.

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

0
ответ дан 24 November 2019 в 07:23
поделиться

Этот ответ больше предназначен для выяснения того, сколько модульных тестов использовать для данного метода, который, как вы знаете, вы хотите провести модульное тестирование, из-за его критичности / важности. Используя метод Basis Path Testing МакКейба, вы могли бы сделать следующее, чтобы количественно получить большую уверенность в покрытии кода, чем простое «покрытие операторов» или «покрытие ветвей»:

  1. Определите значение цикломатической сложности вашего метода, которое вы хотите провести модульное тестирование (Visual Studio 2010 Ultimate, например, может рассчитать это за вас с помощью инструментов статического анализа; в противном случае вы можете рассчитать его вручную с помощью метода потокового графа - http://users.csc.calpoly.edu/~jdalbey /206/Lectures/BasisPathTutorial/index.html)
  2. Перечислить базовый набор независимых путей, которые проходят через ваш метод - см. Ссылку выше для примера потокового графа
  3. Подготовьте модульные тесты для каждого независимого базового пути, определенного на шаге 2
0
ответ дан 24 November 2019 в 07:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: