Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Unit Test. Кто использует?

1707  1 2 3 4 5 6 все
  moose местный житель27.10.16 15:10
NEW 27.10.16 15:10 

Навеяно интересной веткой о DC. Расскажите, кто использует. Интересно все: и почему решили использовать, сплошное ли тестирование, сколько времени занимает имплементировать тест (в сравнении с созданием единицы), как часто эти тесты что-нибудь полезное выдают, и что было бы, если бы их не было (ошибка ушла бы в релиз, ее обнаружил бы первый ручной тест, еще что-то).

И сколько единиц у вас в проекте, и какой процент из них охвачен этим делом. Я смотрю, например, в VS2010 можно насоздавать этих тестов на каждый метод. А их - тьма. И нужно затратить время на принятие решения (делать/не делать), на само создание, если делать, возможно, еще протестировать тест несколько раз, чтоб в нем багов не было, в общем, стоит ли всегда овчинка выделки?

#1 
Программист коренной житель27.10.16 15:48
NEW 27.10.16 15:48 
в ответ moose 27.10.16 15:10

Тут надо разделать автоматическое тестирование и Unit Testing.

По большому счету, Unit Testing не имеет смысле вне TDD. Однако все мы живем в реальном мире, а не в мире эльфов, поэтому во-первых, под юнит-тестами понимают все автоматические тесты, во-вторых, о TDD вспоминают исключительно на ретроспективе :D


Что касается нас, то всякими разными тестами у нас покрыто около 65-70% кода. Цель - 80%. Без тестов была бы полная беспросветная жопа. Поэтому тесты крутятся каждый день и рарезультаты тестирования лежат каждое утро в ящике :) Другое дело, что половина тестов у нас непривильные и поэтому если из примерно 1500 тестов 10-20 не сработали, то всем пофиг :) Но это уже другая тема.


Тестировать надо с умом, а не каждый метод :) Если интересна эта тема, то советую прочитать Roy Osherove - The Art of Unit Testing

#2 
natuerlich blond старожил27.10.16 19:51
natuerlich blond
NEW 27.10.16 19:51 
в ответ moose 27.10.16 15:10

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

Но я считаю, что юнит-тестинг необходим по ряду причин:

- тестируешь чисто для себя, правильно ли работает твоя функция

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

- не нужно запускать приложение, чтобы проверить, работает ли функция

- если другие написали тесты, то ты можешь проверить, не сломал ли ты что-то

При этом нужно исходить из того, что тесты имеют смысл и не подогнаны под имплементацию.


Это что касается юнит-тестинга. Но здесь нужно учитывать, что такие тесты как правило делаются на моках, а значит не позволяют тестировать übergreifend, тестирование UI тоже очень ограничено, если вообще возможно. Поэтому необходимо интеграционное тестирование, а также для Last и Performance.

#3 
Murr_0001 знакомое лицо27.10.16 20:13
Murr_0001
NEW 27.10.16 20:13 
в ответ moose 27.10.16 15:10

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

-----

По сумме - около 2Гб кода. Код, в основном, ВБ-лике - переменные, функции, функции, функции...



какой процент из них охвачен этим делом

-----

Исходный код - 0%, в переработанном коде - 5-6%% - не хватает времени на написание...



сколько времени занимает имплементировать тест (в сравнении с созданием единицы)

-----

от 10 минут до пары дней... бывает - с перерывами на неделю-месяц-полгода...

базовый юнит делается от 5 минут до пары часов, дополнительный функционал - от 0 до пары дней...

#4 
AlexNek патриот28.10.16 00:11
AlexNek
NEW 28.10.16 00:11 
в ответ moose 27.10.16 15:10

не думаю, что есть какой либо универсальный ответ. Всё зависит от конкретной ситуации.

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

Как раз был такой случай, тестер так модули вызвал, что мы бы никогда бы не додумались о данной комбинации, ну и конечно, работало не так как требовалось. Пришлось довольно много переписывать.


Сделать покрытие тестами хотя бы больше 50% кода достаточно затратно, а при подъеме покрытия наверх затраты резко возрастают. При этом чем больше тестов, тем больше проблем, особенно когда они "перестают работать".

Часто проблемы "приятные" - видно что нахренячил кто то. А бывает, что после продолжительного анализа так и непонятно отчего тест перестал работать. "Интересно" также искать ошибки, когда последовательность вызова тестов меняется.


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

С другой стороны тесты, тоже не "золотая пуля". Даже если тесты не дают ни одной ошибки - это еще не означает что продукт работает безошибочно.

#5 
Simple Nothing is f*cked28.10.16 10:45
Simple
NEW 28.10.16 10:45 
в ответ moose 27.10.16 15:10

У меня все проекты - легаси, никаких тестов там нет от слова "ваще". Что приводит иногда к интересным феноменам в продакшн типа NPE :(

Мечтаю когда-нить поработать в проекте с использованием тдд или типа того.

#6 
  moose местный житель28.10.16 11:38
NEW 28.10.16 11:38 
в ответ Программист 27.10.16 15:48, Последний раз изменено 28.10.16 11:59 (moose)

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

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

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

Ладно, прочту книгу, наверняка человеческий опыт что-нибудь нового подкинет.

#7 
kitov знакомое лицо28.10.16 11:53
NEW 28.10.16 11:53 
в ответ Simple 28.10.16 10:45

У меня все проекты - легаси, никаких тестов там нет от слова "ваще". Что приводит иногда к интересным феноменам в продакшн типа NPE :(

Мечтаю когда-нить поработать в проекте с использованием тдд или типа того.

Даже с легаси можно применять практики ТДД. На эту тему есть неплохая книга -> https://www.amazon.de/Working-Effectively-Legacy-Robert-Ma...

#8 
Simple Nothing is f*cked28.10.16 12:35
Simple
NEW 28.10.16 12:35 
в ответ kitov 28.10.16 11:53

Да, я ее читал, когда работал с одним жутким с++-монстром. К сожалению, трудно объяснить клиенту, что времени не хватает, когда на один вонючий юнит-тест уходит целый день.

#9 
Программист коренной житель28.10.16 12:56
NEW 28.10.16 12:56 
в ответ moose 28.10.16 11:38
Или что-то не так понимаю?

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


Что касается твоего примера с конкатенатом, то тут слишком простой пример :) Представь себе функцию с cyclomatic complexity 5 или больше :) да еще с вызовами каких-нибудь других функций (самое убийственное, если эти функции статические да еще 3rd party) :). Результат такой функции может легко поменяться после банального апдейся какой-нибудь сторонней системы ;)


#10 
Пирт гость28.10.16 19:10
28.10.16 19:10 
в ответ moose 28.10.16 11:38, Последний раз изменено 28.10.16 19:13 (Пирт)

У нас все о них говорят, и о TDD. О TDD - что, мол, "мы следуем", но при этом никакого TDD и в помине нет (это тот еще философский вопрос, надо ли).

Покрытие кода у нас 60-70%, полет нормальный =)


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


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

#11 
  moose местный житель28.10.16 23:29
NEW 28.10.16 23:29 
в ответ Пирт 28.10.16 19:10, Последний раз изменено 28.10.16 23:31 (moose)

О "человеке" Вы истину написали. Мой опыт: шеф имеет одного человека, мнению которого доверяет. Этот человек "уснул" где-то году в 2000-м, но на все сразу имеет готовый категоричный ответ ("ВСЕ - КОЗЛЫ!" pattern).

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


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

"Никаких проблем" (с)


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

#12 
AlexNek патриот28.10.16 23:43
AlexNek
NEW 28.10.16 23:43 
в ответ moose 28.10.16 11:38
Т.е. по определению та же ф-я с теми же данными должна выдавать одинаковый результат

Определение нужно уточнить, что функция не должна при этом:

- иметь побочных эффектов.

- использовать другие классы/функции. В том числе и системные.


Когда он закончен и все тесты прошли - закомментирую

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

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


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

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

А для строк бывает достаточно сменить язык, чтобы "житроумный метод" накернулся.


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

Это еще одна проблема тестов, нужно постоянно думать чтобы ему еще такое скормить, чтобы накернулся.

#13 
  moose местный житель28.10.16 23:59
NEW 28.10.16 23:59 
в ответ AlexNek 28.10.16 23:43, Последний раз изменено 29.10.16 00:00 (moose)

В конце-концов мы забываем, что мы вообще-то разрабатываем: тесты или что-то другое : ) Звоним клиенту: продукт - говно, но тесты - супер! И все проходят! Берите - не пожалеете!

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

- Вы программируете объекно-ориентированно (Вы применяете TDD/SCRUM/UT/...костыль №6)?

- Да, конечно!

- Это хорошо!

#14 
AlexNek патриот29.10.16 01:46
AlexNek
NEW 29.10.16 01:46 
в ответ moose 28.10.16 23:59
А если технология/методология входит в моду - каждый пыжится ее применить

Ну вообще то это самый фиговый подход.

Работал как то с одним, который любил обо всём новом читать и тут же это применять. Бо, сколько натерпелись....

#15 
Программист коренной житель29.10.16 07:57
NEW 29.10.16 07:57 
в ответ moose 28.10.16 23:59
По мне дак пока плотют - буду дома книги читать и вправы упражнять, а на работе - "как все".

Это ты зря ;) На работе должно быть интересно. Если стало не интересно, то надо уходить. ИМХО.


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

Начнем с того, что клиенту пофиг на технологию :)

Ну если только это какой-то заказной софт и клиент выступает в роли Product Owner'а :) Не знаю случается ли такое, но почему нет?


Применять технологию из-за того, что это модно - это как минимум странно. Помню, когда у нис вводили скрам, то носились с ним все как золотым граалем из которого полезет совершенный код :) Люди реально верили, что технология менеджмента может как-то повысить качество создаваемого кода. Сейчас скрам у нас занимает около 20% рабочего времени :F при этом все как-то умудряются работать "по скраму", но при этом работа идет также как и раньше. Т.е. от скрама мы взяли только скучнейшие совещания ну и какое-то подобие планирования. Вообще у нас забавно получилось. На первом этапе роли продакт онера и скрам мастера совмещал наш тимлид :) Где-то через год нам назначили скрам мастера, но тимлид не сдает своих позиций :) и все также выполняет обе роли :D


#16 
bobkov постоялец29.10.16 23:37
bobkov
NEW 29.10.16 23:37 
в ответ moose 27.10.16 15:10
в общем, стоит ли всегда овчинка выделки?

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

#17 
Программист коренной житель30.10.16 00:13
NEW 30.10.16 00:13 
в ответ bobkov 29.10.16 23:37, Последний раз изменено 30.10.16 17:56 (Программист)
По моему скромному мнению, надо покрывать Unit-тестами часто используемые функции (если в ООП, то классы).

Интересно, как определить это "часто"? Где граница?


Вот например такой код:

public interface Content
{
string GetContent(string path);
}

public class HttpContent : Content
{
public string GetContent(string url)
{
string content = null;

// Open connection

// download some information

// Close connection

return content;
}

public byte[] GetBinaryData(string url)
{
byte[] buf = null;

// Open connection

// download binary data

// Close connection

return buf;
}
}

public class DiskContent : Content
{
public string GetContent(string url)
{
string content = null;

// Open file

// read file

// Close file

return content;
}
}

public class SomeTool
{
public Content Content { get; private set; }

public SomeTool(Content content)
{
Content = content;
}

public string GetContent(string path)
{
return Content.GetContent(path);
}
}

public class SomeOtherClass
{
public SomeTool Tool { get; private set; }

public SomeOtherClass(Content content)
{
Tool = new SomeTool(content);
}

public string GetUserInfo()
{
return Tool.GetContent(@"some path\user");
}

public string GetFirmInfo()
{
return Tool.GetContent(@"some path\firm");
}

public string GetProductInfo()
{
return Tool.GetContent(@"some path\product");
}
}

Очевидно, что часто используемая функция тут SomeTool.GetContent (на нее идет целых 3 ссылки). Вот только надо ли ее тестировать? :)

Сдается мне, что оценка количества вызовов - неработающая оценка.

#18 
Murr_0001 знакомое лицо30.10.16 09:25
Murr_0001
NEW 30.10.16 09:25 
в ответ bobkov 29.10.16 23:37

Ну у меня аккурат описанная тобою ситуация - абстрактный слой, поверх которого строятся бизнес-объекты.

И как раз в этот абстрактный слой не так давно внесены изменения.

Слой оттестирован - все методы работают как ожидается.

А вот все остальное - не работает. смущ Несмотря на то, что часть тестов там отрабатывают... но там покрытие в 0,5%...

#19 
  moose местный житель30.10.16 11:27
NEW 30.10.16 11:27 
в ответ Программист 30.10.16 00:13

Это у Вас случайно ни один из классов не наследует интерфейс Content, или так задумано. Если задумано, то поясните.

#20 
1 2 3 4 5 6 все