Основные jUnit Вопросы

Я тестировал Строковый класс множителя с a multiply() метод, который берет 2 числа в качестве исходных данных (как String) и возвращает число результата (как String)

public String multiply(String num1, String num2);      

Я сделал реализацию и создал тестовый класс со следующими тестовыми сценариями, включающими параметр входной строки как

  1. верные номера
  2. персонажи
  3. специальный символ
  4. пустая строка
  5. Нулевое значение
  6. 0
  7. Отрицательное число
  8. плавание
  9. Граничные значения
  10. Номера, которые являются верными, но их продукт вне диапазона
  11. числа будут + знак (+23)

Теперь мои вопросы - они:

  1. Я хотел бы знать, должен ли "каждый" assertEquals () быть в своем собственном методе тестирования? Или, действительно ли я могу сгруппироваться, подобные тестовые сценарии как testInvalidArguments () к содержит, все утверждает недопустимые символы вовлечения, так как Все они бросают тот же NumberFormatException?

  2. При тестировании входного значения как символ ("a"), я должен включать тестовые сценарии для ВСЕХ сценариев? "a" как первый аргумент "a" как второй аргумент "a" и "b" как эти 2 аргумента

  3. Согласно моему пониманию, преимущество этих модульных тестов состоит в том, чтобы узнать случаи, где вход от пользователя мог бы перестать работать и привести к исключению. И, затем мы можем дать пользователю со значимым сообщением (просьба, чтобы они обеспечили допустимый вход) вместо исключения. Это - корректное? И, действительно ли это - единственное преимущество?

  4. Эти 11 тестовых сценариев упомянуты выше достаточные? Я пропускал что-то? Я переусердствовал? Когда достаточно?

  5. При следовании из вышеупомянутой точки я успешно протестировал умножение () метод?

8
задан Joachim Sauer 26 April 2010 в 09:37
поделиться

6 ответов

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

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

3) Цель модульного тестирования - обеспечить уровень уверенности в том, что тестируемые методы выполняют то, что от них требуется. Что это означает, зависит от тестируемого кода. Например, если я выполняю модульное тестирование метода sort , проверка пользовательского ввода не имеет значения.

4) Покрытие кажется разумным. Однако без подробного описания того, что должен делать ваш класс, и без изучения реальных модульных тестов, невозможно сказать, все ли вы охватили.Например, должен ли ваш метод работать с начальными / конечными пробельными символами, числами с десятичными точками, числами типа «123,456», числами, выраженными нелатинскими цифрами, числами с основанием 42?

5) Определите «успешно протестировано» . Если вы имеете в виду, доказывают ли мои тесты отсутствие ошибок в коде, то ответ однозначный «НЕТ».Если модульные тесты не перечисляют все возможные входные данные, они не могут служить доказательством правильности. (А в некоторых случаях даже тестирования всех входных данных бывает недостаточно.)

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

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

4
ответ дан 5 December 2019 в 08:22
поделиться

Истинное количество тестов, конечно, бесконечно. Это непрактично. Вы должны выбрать допустимые репрезентативные кейсы. Похоже, вы это сделали. Молодец.

2
ответ дан 5 December 2019 в 08:22
поделиться

1) Я действительно считаю хорошей идеей ограничить количество утверждений, которые вы делаете в каждом тесте. JUnit сообщает только о первом сбое в тесте, поэтому, если у вас есть несколько утверждений, некоторые проблемы могут быть замаскированы. Более полезно иметь возможность видеть все, что прошло, и все, что не удалось. Если у вас есть 10 assertEquals в одном тесте, а первый не прошел, тогда вы просто не знаете, что произошло бы с другими 9. Это были бы хорошие точки данных, которые нужно иметь при отладке.

2) Да, вы должны включить тесты для всех ваших входных данных.

3) Необходимо тестировать не только вводимые пользователем данные. Вы захотите написать тесты для любых общедоступных методов, которые могут дать сбой. В JUnit FAQ есть несколько хороших рекомендаций для этого, особенно в отношении геттеров и сеттеров.

4) Думаю, у вас это довольно хорошо описано. (По крайней мере, я не могу думать ни о чем другом, но вижу № 5).

5) Раздайте его некоторым пользователям для тестирования. Они всегда находят образцы данных, которые я никогда не думаю о тестировании. :)

5
ответ дан 5 December 2019 в 08:22
поделиться

Я просто хочу добавить, что с модульным тестированием вы можете получить еще больше, если сначала подумайте о возможных случаях, а затем внедрите в тестируемый development, потому что это поможет вам сосредоточиться на текущем случае, и это позволит вам создать самую простую возможную реализацию в режиме DRY. Вы также можете использовать какой-нибудь инструмент для покрытия тестов, например в Eclipse EclEmma, ​​который действительно прост в использовании и покажет вам, выполнили ли тесты весь ваш код, что может помочь вам определить, когда этого достаточно (хотя это не доказательство, а просто показатель). Как правило, когда дело доходит до модульного тестирования, меня очень вдохновила книга Кента Бекса «Разработка через тестирование на примерах», я настоятельно рекомендую ее.

1
ответ дан 5 December 2019 в 08:22
поделиться

Модульное тестирование - это здорово (в проекте 200 KLOC, над которым я работаю, у меня столько же кода модульного теста, сколько и обычного кода), но (при условии правильного модульного теста):

  • успешно пройденный модульный тест выполняет not гарантирует, что ваш код работает

Подумайте об этом так:

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

Это действительно важно понимать.

В дополнение к этому:

  • обычно невозможно протестировать все возможные входные данные

А затем, когда вы выполняете рефакторинг:

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

Но:

  • если один из ваших модульных тестов терпит неудачу, вы знаете, что вы ввели регрессию

Это действительно фундаментально и должно быть модульное тестирование 101.

{{1 }}
6
ответ дан 5 December 2019 в 08:22
поделиться

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

Однако вместо ручного написания теста для каждого отдельного «недопустимого сценария» вы можете взглянуть на теории JUnit 4.4 (см. примечания к выпуску JUnit 4.4 и этот блог post ) или средство запуска тестов JUnit Parameterized .

Параметризованные тесты и теории идеально подходят для таких «расчетных» методов, как этот. Кроме того, чтобы все было организовано, я мог бы сделать два тестовых класса: один для «хороших» входных данных, а второй - для «плохих».

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

3) Написание модульных тестов дает множество преимуществ, не только то, о котором вы упомянули. Некоторые другие преимущества включают:

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

5) Похоже, вы хорошо поработали, придумав возможные сценарии тестирования. Думаю, у тебя есть все важные.

2
ответ дан 5 December 2019 в 08:22
поделиться
Другие вопросы по тегам:

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