Лучшие практики в написании юнит-тестов - PullRequest
3 голосов
/ 21 января 2011

У меня вопрос "передового опыта". Я пишу тест для определенного метода, но есть несколько значений ввода. Должен ли я написать один тест для каждого входного значения или изменить значение переменной entryValues ​​и вызвать метод .assert () (делая это для всего диапазона возможных значений)?

Спасибо за вашу помощь. С уважением,

Педро Магуэйя

отредактировано: я использую .NET. Visual Studio 2010 с VB.

Ответы [ 6 ]

5 голосов
/ 21 января 2011

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

2 голосов
/ 21 января 2011

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

1 голос
/ 22 января 2011

Должен ли я написать один тест для каждой записи значение или я должен изменить значение переменной entryValues ​​и вызов метод .assert () (делает это для всех диапазон возможных значений)?

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

Например, если у меня есть функция

define add_one(num) {
  return num+1;
}

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

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

define execute(directive) {
  if (directive == 'quit') { exit; }
  elsif (directive == 'help') { print help; }
  elsif (directive == 'connect') { intialize_connection(); }
  else { warn("unknown directive"); }
}

Для ясности я использовал elifs, а не таблицу отправки. Я думаю, это дает понять, что каждое уникальное значение имеет свое поведение, и поэтому вам нужно будет проверить каждое возможное значение.

1 голос
/ 21 января 2011
  1. Меньшие тесты легче читать.
  2. Имя является частью документации теста.
  3. Отдельные методы дают более точное представление о том, что не удалось.

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

void testAll() {
  // setup1
  assert()
  // setup2
  assert()
  // setup3
  assert()
}

По моему опыту, это становится очень большим очень быстро, и поэтому становится трудно читать и понимать, поэтому я бы сделал:

void testDivideByZero() {
  // setup
  assert()
}

void testUnderflow() {
  // setup
  assert()
}


void testOverflow() {
  // setup
  assert()
}
0 голосов
/ 21 января 2011

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

1) если ваш тестовый фреймворк поддерживает это, используйте RowTest, MBUnit и Nunitподдержите это, если вы используете .NET, это позволит вам поместить несколько атрибутов в ваш метод, и каждая строка будет выполняться как отдельный тест

2) Если не написать тест для каждого условия и убедиться, что вы его далиосмысленное имя, так что если (когда) тест не пройден, вы можете легко найти проблему и что-то для вас.

РЕДАКТИРОВАТЬ Ее называют TestCase in Nunit Nunit TestCase Explination

0 голосов
/ 21 января 2011

Вы говорите об этой разнице?

- (void) testSomething
{
    [foo callBarWithValue:x];
    assert…
}

- (void) testSomething2
{
    [foo callBarWithValue:y];
    assert…
}

против

- (void) testSomething
{
    [foo callBarWithValue:x];
    assert…
    [foo callBarWithValue:y];
    assert…
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...