Объясните модульное тестирование, пожалуйста

#unit-testing #testing

#модульное тестирование #тестирование

Вопрос:

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

Теперь, при тестировании, я хотел бы знать такие вещи, как: находит ли поиск первый элемент, последний элемент и другие элементы? Правильно ли поиск сравнивает символы Юникода. Обрабатывает ли поиск символы и другие «болезненные» символы. Будет ли модульное тестирование охватывать это, или я это пропускаю? Как бы вы написали модульные тесты для моего двоичного поиска?

 function search(collection, value){
 var start = 0, end = collection.length - 1, mid;
 while (start <= end) {
  mid = start   ((end - start) / 2);
  if (value == collection[mid])
   return mid;
  if (collection[mid] < value)
   end = mid - 1;
  else
       start = mid   1;
 }
 return mid;
}
  

Псевдокод для модульных тестов был бы прекрасен.

Итак, у нас может быть:

 function testFirst(){
 var collection = ['a','b','c','x','y','z'],first = 'a', findex = 0;
 assert(seach(collection,first),findex);
}
function testLast(){
 var collection = ['a','b','c','x','y','z'], last = 'z', lindex = 5;
 assert(seach(collection,last),lindex);
}
  

Ответ №1:

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

Ответ №2:

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

Я думаю, что многие люди упускают из виду одно значение модульного тестирования — это то, что его ценность увеличивается со временем. Когда я пишу фрагмент кода и модульный тест, я в основном только что проверил, что код выполняет то, что я думаю, что он должен, что он не дает сбоев ни в одном из способов, которые я решил проверить, и т.д. Это хорошие вещи, но они имеют ограниченную ценность, потому что они выражают знания, которые у вас есть о системе на данный момент; они не могут помочь вам с вещами, о которых вы не знаете (есть ли в моем алгоритме скрытая ошибка, о которой я не знаю и не подумал протестировать?).

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

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

Другое значение — это значение проверки; по мере того, как код продолжает существовать в проектах, все подвергается рефакторингу, изменениям и смещению. Модульные тесты обеспечивают подтверждение того, что компонент, который, как вы думали, работал одним способом, продолжает работать таким образом. Это может быть бесценно, помогая находить ошибки, которые проникают в проекты. Например, изменение решения для базы данных иногда может быть прозрачным, но иногда эти изменения могут вызвать неожиданные изменения в том, как работают некоторые вещи; модульное тестирование компонентов, которые зависят от вашего ORM, может выявить критические тонкие изменения в базовом поведении. Это действительно становится полезным, когда у вас есть фрагмент кода, который безупречно работает годами, и никто не думает учитывать его потенциальную роль в сбое; на поиск ошибок такого типа может потребоваться ОЧЕНЬ много времени, потому что последнее место, где вы собираетесь искать, — это компонент, который был безупречен в течение очень долгого времени. Модульное тестирование обеспечивает проверку этой «прочности скалы».

Ответ №3:

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

В вашем случае настройка ‘collection’ с некоторыми конкретными значениями (или без значений) устанавливает предварительные условия.

Вызов вашего метода поиска с определенным параметром запускает тестируемый код.

Проверка того, что значение, возвращаемое вашим методом, соответствует ожидаемому, является шагом утверждения.

Дайте этим трем элементам имя, которое описывает то, что вы пытаетесь сделать (Doesthesearchmethod Failifcollectionisempty) и вуаля, у вас есть модульный тест.