Что и как следует покрывать юнит-тестами
От: FrozenHeart  
Дата: 30.12.15 11:59
Оценка:
Привет всем!

Я думаю, все здесь считают, что написание юнит-тестов -- это неотъемлимая часть разработки любого более-менее порядочного программного обеспечения, не так ли?

Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?

Я вот, например, до сих пор не могу понять, как можно писать тесты в некоторых случаях. Например, пишу я агрегатор объявлений с avito.ru на Python. Использую при этом фреймворк под названием Scrapy, который абстрагирует меня практически от всего (HTTP-реквесты, переподключения, редиректы etc). Всё, что мне остаётся -- вытащить из результата, переданного в мой callback в виде HTML-страницы, несколько значений, после чего записать их в БД / Excel-файл / etc. Что при таком подходе можно тестировать? Успешность выполнения GET-реквестов и валидность данных, которые прилетают мне в ответе? Так они выполняются где-то в недрах фреймворка, я даже знать-не знаю, какие там методы вызываются и что конкретно происходит. Даже если я посмотрю в исходники и увижу, что на самом нижнем слое находится, например, urllib из стандартной библиотеки Python, то полагаться на недокументированное поведение, на мой взгляд, в данном случае глупо. Успешность записи данных в БД / Excel-файл? Первое вообще непонятно, как зафейлиться может (разве что структура таблиц не совпадает с используемой мной моделью), второе ещё ладно.

В общем, поделитесь советами на тему того, что и как следует покрывать тестами, а что следует оставлять без покрытия. Чем вы руководствуетесь при написании юнит-тестов?
Re: Что и как следует покрывать юнит-тестами
От: andrey82  
Дата: 30.12.15 12:28
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>Всё, что мне остаётся -- вытащить из результата, переданного в мой callback в виде HTML-страницы, несколько значений, после чего записать их в БД / Excel-файл / etc. Что при таком подходе можно тестировать?


В приведенном примере — разве что выделенное. Хотя полезность тоже под сомнением, т.к. входные данные (структура страницы) может меняться со временем и тесты надо будет дорабатывать. Полезнее в данном случае будет внутри рабочего кода добавить проверки по входу и по выходу (ассерты + исключения / логгирование или как там принято в Питоне).
Re: Что и как следует покрывать юнит-тестами
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.12.15 13:02
Оценка: +1
Здравствуйте, FrozenHeart, Вы писали:

FH>Я думаю, все здесь считают, что написание юнит-тестов -- это неотъемлимая часть разработки любого более-менее порядочного программного обеспечения, не так ли?


FH>Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?


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

Обычно тест у меня обычно специальное консольное приложение, которое принимает имя теста в командной строке и выполняет его. Написал свой test-driver для autotools, который получает список всех тестов, потом запускает их (опционально под valgrind, задаётся в configure-скрипте). Для некоторых консольных программ сделал примитивный аналог DejaGnu: простенький файл входа/выхода, запуск под valgrind, проверка, совпадают ли результаты... Пробовал DejaGnu, но как-то не пошло...
Re: Что и как следует покрывать юнит-тестами
От: Зверёк Украина https://zverok.github.io
Дата: 30.12.15 13:30
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?


Всегда. Ruby+RSpec.

FH>Я вот, например, до сих пор не могу понять, как можно писать тесты в некоторых случаях. Например, пишу я агрегатор объявлений с avito.ru на Python. Использую при этом фреймворк под названием Scrapy, который абстрагирует меня практически от всего (HTTP-реквесты, переподключения, редиректы etc). Всё, что мне остаётся -- вытащить из результата, переданного в мой callback в виде HTML-страницы, несколько значений, после чего записать их в БД / Excel-файл / etc. Что при таком подходе можно тестировать? Успешность выполнения GET-реквестов и валидность данных, которые прилетают мне в ответе? Так они выполняются где-то в недрах фреймворка, я даже знать-не знаю, какие там методы вызываются и что конкретно происходит. Даже если я посмотрю в исходники и увижу, что на самом нижнем слое находится, например, urllib из стандартной библиотеки Python, то полагаться на недокументированное поведение, на мой взгляд, в данном случае глупо. Успешность записи данных в БД / Excel-файл? Первое вообще непонятно, как зафейлиться может (разве что структура таблиц не совпадает с используемой мной моделью), второе ещё ладно.


Ну, это. Описываем что делает код русским языком, тестируем что он делает именно это.
В описанном случае, я бы сделал следующее:

1. заглушку на релевантные урлы, возвращающую заранее сохранённые данные (в руби есть для этого webmock, позволяющий поставить заглушку на «запросы вообще», вне зависимости от того какой конкретной библиотекой они выполняются; в питоне есть по-моему FakeWeb для этого)
* можно также использовать библиотеку автоматической записи реквестов (в руби есть vcr, в питоне наверняка есть аналог) — тогда время от времени стирая закешированные реквесты, можно убеждаться, что какой-нибудь мелкий редизайн авито не сломал код
2. дальше стандартное тестирование happy и unhappy pathes:
* когда я свою библиотеку вызываю для такого-то раздела, она выполняет запрос всех объявлений этого раздела
* когда я свою библиотеку вызываю для такого-то объявления, она выполняет разбор объявления и пишет его в БД
* когда я свою библиотеку вызываю для отсутствующего раздела, она делает что-то предсказуемое
* когда в объявлении не хватает нужных для моего кейса данных/объявление ненужное/что-там-у-вас-ещё-может-случиться — происходит что-то предсказуемое
....
Re: Что и как следует покрывать юнит-тестами
От: Sharov Россия  
Дата: 30.12.15 15:10
Оценка:
Здравствуйте, FrozenHeart, Вы писали:


Поскольку над проектом работаю один, от ЮТ отказался и пишу интеграционные(функциональные) тесты.
FH>Привет всем!

FH>Я думаю, все здесь считают, что написание юнит-тестов -- это неотъемлимая часть разработки любого более-менее порядочного программного обеспечения, не так ли?


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

FH>Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?


C#. Написал свой опереточный фреймворк для прогона интеграционных тестов.

FH>Я вот, например, до сих пор не могу понять, как можно писать тесты в некоторых случаях. Например, пишу я агрегатор объявлений с avito.ru на Python. Использую при этом фреймворк под названием Scrapy, который абстрагирует меня практически от всего (HTTP-реквесты, переподключения, редиректы etc). Всё, что мне остаётся -- вытащить из результата, переданного в мой callback в виде HTML-страницы, несколько значений, после чего записать их в БД / Excel-файл / etc. Что при таком подходе можно тестировать? Успешность выполнения GET-реквестов и валидность данных, которые прилетают мне в ответе? Так они выполняются где-то в недрах фреймворка, я даже знать-не знаю, какие там методы вызываются и что конкретно происходит. Даже если я посмотрю в исходники и увижу, что на самом нижнем слое находится, например, urllib из стандартной библиотеки Python, то полагаться на недокументированное поведение, на мой взгляд, в данном случае глупо. Успешность записи данных в БД / Excel-файл? Первое вообще непонятно, как зафейлиться может (разве что структура таблиц не совпадает с используемой мной моделью), второе ещё ладно.


Перед запускам каждого теста (или всех сразу) поднимать какой-то сервис глушилку, который бы отдавал заранее известные данные, проверять что ответ соотв. ожидаемому, сохранять в бд, проверить, что все сохранилось нормально. Что касается сторонних библиотек, то тут ничего не попишешь: если у них баг, то репортите им, если очень срочно, то исправляйте сами.
Кодом людям нужно помогать!
Re[2]: Что и как следует покрывать юнит-тестами
От: FrozenHeart  
Дата: 30.12.15 15:35
Оценка:
S>Перед запускам каждого теста (или всех сразу) поднимать какой-то сервис глушилку, который бы отдавал заранее известные данные, проверять что ответ соотв. ожидаемому, сохранять в бд, проверить, что все сохранилось нормально

Т.е. подсовывать заранее заготовленную HTML-страницу? Если да, то тесты пройдут успешно, если даже вёрстка настоящего сайта уже давно поменялась, что вызовет некорректную работу приложения уже в процессе работы.
Re[2]: Что и как следует покрывать юнит-тестами
От: FrozenHeart  
Дата: 30.12.15 15:39
Оценка:
Зё>1. заглушку на релевантные урлы, возвращающую заранее сохранённые данные (в руби есть для этого webmock, позволяющий поставить заглушку на «запросы вообще», вне зависимости от того какой конкретной библиотекой они выполняются; в питоне есть по-моему FakeWeb для этого)

Тот же самый вопрос, что я задал в соседней ветке.

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

Зё>* можно также использовать библиотеку автоматической записи реквестов (в руби есть vcr, в питоне наверняка есть аналог) — тогда время от времени стирая закешированные реквесты, можно убеждаться, что какой-нибудь мелкий редизайн авито не сломал код


Если я правильно понял, как это работает, то мне всё равно в тестах надо будет указать реальный адрес страниц, на которые я буду выполнять реквесты, верно? Если так, то с avito такая тема не прокатит -- объявления не живут вечно, URL'ы в тестах со временем станут неактуальны.
Re[3]: Что и как следует покрывать юнит-тестами
От: Sharov Россия  
Дата: 30.12.15 15:55
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

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


FH>Т.е. подсовывать заранее заготовленную HTML-страницу? Если да, то тесты пройдут успешно, если даже вёрстка настоящего сайта уже давно поменялась, что вызовет некорректную работу приложения уже в процессе работы.


Да, заранее заготовленную HTML-страницу. В любом случае приложение упадет после изменения страницы. Тут надо либо постоянно подстраиваться, либо искать другие подходы и т.д. У avito должно же быть какое-нибудь REST API? А тесты на то и нужны, чтобы проверять код по заранее известным входным данным.
Кодом людям нужно помогать!
Re[3]: Что и как следует покрывать юнит-тестами
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.12.15 16:02
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>Т.е. подсовывать заранее заготовленную HTML-страницу? Если да, то тесты пройдут успешно, если даже вёрстка настоящего сайта уже давно поменялась, что вызовет некорректную работу приложения уже в процессе работы.


Тестирование GUI это отдельная песня, тут надо смотреть в направлении систем, наподобие Sikuli. Юнит-тесты для такого бесполезны.
Отредактировано 30.12.2015 16:06 Mystic . Предыдущая версия .
Re[3]: Что и как следует покрывать юнит-тестами
От: Зверёк Украина https://zverok.github.io
Дата: 30.12.15 16:05
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

Зё>>1. заглушку на релевантные урлы, возвращающую заранее сохранённые данные (в руби есть для этого webmock, позволяющий поставить заглушку на «запросы вообще», вне зависимости от того какой конкретной библиотекой они выполняются; в питоне есть по-моему FakeWeb для этого)


FH>Тот же самый вопрос, что я задал в соседней ветке.


FH>Т.е. подсовывать заранее заготовленную HTML-страницу? Если да, то тесты пройдут успешно, если даже вёрстка настоящего сайта уже давно поменялась, что вызовет некорректную работу приложения уже в процессе работы.


Ну в зависимости от сайта, я же навскидку говорю. В принципе, тесты можно (и зачастую нужно) делить модульные и интеграционные, например.
В данном случае «модульный тест» работает на заглушке, интеграционный — на реальных данных, например.
Интеграционный гоняется реже/отдельно.
Сломался интеграционный с сигналом «вёрстка того» — переделал модульные на новых заглушках.

Зё>>* можно также использовать библиотеку автоматической записи реквестов (в руби есть vcr, в питоне наверняка есть аналог) — тогда время от времени стирая закешированные реквесты, можно убеждаться, что какой-нибудь мелкий редизайн авито не сломал код


FH>Если я правильно понял, как это работает, то мне всё равно в тестах надо будет указать реальный адрес страниц, на которые я буду выполнять реквесты, верно? Если так, то с avito такая тема не прокатит -- объявления не живут вечно, URL'ы в тестах со временем станут неактуальны.


Ну можно начинать с какого-то урла раздела, который присутствует всегда. И тесты формулировать как «найдено X объявлений, у каждого есть автор, дата, (что вам там ещё важно)».
Re: Что и как следует покрывать юнит-тестами
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 30.12.15 19:56
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?


Важно определиться с тем какую проблему ты решаешь. Тесты это не улучшайзер, это проверка качества. Если вспомнить, что качество это степень соответствования требованиям, то сразу вопрос — какие требования ?

Вот например ты пилишь компонент, который кидает эвент ready когда его состояние из loading стало complete. Вопрос- как ты к этому пришел ?
Например было так — "мы решили что здесь будет эвент". В этом случае никаких тестов писать нет смысла.
А если ты взял какую формальную модель, спроектировал на ее основе решение, то, внезапно, есть смысл проверить, обладает ли твое решение требуемыми свойствами формальной модели
Естественно, проверяешь не все, а только ту часть, на которую полагается вызывающий код. А именно
1 поведение
2 вычисления
3 реакция — сигналы об изменениях состояния
4 инварианты
5 пред и пост условия

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

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

Требования часто неявные. Например требуется реализовать интерфейс, а дальше хоть так, хоть иначе, хоть как угодно. Фокус в том что код должен быть изначально проектироваться как тестопригодный, если ты планируешь покрывать тестами. Самый лучший вариант это функции навроде sin cos tan — тоесть, без состояния. Изменения состояния нужно протаскивать отдельной бухгалтерией.

Скажем, если ты свел решение к автомату с магазином, то стоит тестировать не все, а только функцию переходов(поведение) и АПИ автомата. Тестировать все тотально смысла не имеет

Самый главный принцип — красный юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а 'метод сенд актора обнуляет бехевиор если была ошибка'

UPD: На примере автомата — тесты функции переходов если в лоб, то это довольно хрупкие тесты. Вместо таких тестов есть вариант — четкая формальная модель автомата. Дальше покрывать тестами само поведение, здесь автомат должен быть изолирован от БД и прочих вещей.
Если автомат сделан в духе 'большой свич' то имеет смысл выразить все фокусы с переходами в виде тестов. Они будут хрупкими, но будут четко показывать, какой переход некорректный.
Собтсвенно, тесты поведения так же будут хрупкими. Например если состояние было открыто или закрыто, а стало начинаем открывать и открытие завершено и начинаем закрывать- закрытие завершено, то все тесты придется выбросить.
Отредактировано 31.12.2015 21:17 Pauel . Предыдущая версия .
Re[2]: Что и как следует покрывать юнит-тестами
От: Yoriсk  
Дата: 04.01.16 10:44
Оценка: +1 -1
Здравствуйте, Ikemefula, Вы писали:

I>Самый главный принцип — красный юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а 'метод сенд актора обнуляет бехевиор если была ошибка'


Нет, не должен.
Потому что это не только бесполезно — зная об ошибке в определённом сценарии ты её и так найдёшь, т.е. ценна именно информация "у нас что-то не так", всё остальное приложится само собой — но и просто вредно, т.к. для более лучшего указания на источник ошибки начинается тестирование геттеров-сеттеров, конструкторов типа { this.param1 = param1; this.param2 = param2; } и прочие невероятно полезеные практики, столь улучшающин проценты метрик и столь тешащие сердца менеджмента.
Re[3]: Что и как следует покрывать юнит-тестами
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.01.16 20:10
Оценка: -1 :)
Здравствуйте, Yoriсk, Вы писали:

I>>Самый главный принцип — красный юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а 'метод сенд актора обнуляет бехевиор если была ошибка'


Y>Нет, не должен.

Y>Потому что это не только бесполезно — зная об ошибке в определённом сценарии ты её и так найдёшь,

А временем на поиски можно пренебречь ? Вообще то юнит-тесты избавляют от дебага. Классика юнит-тестирования — код теста содержит минимум кода и один-два ассерта. Отсюда ясно, что ошибка видна практически сразу, без необходимости дебага и поисков.

>т.е. ценна именно информация "у нас что-то не так", всё остальное приложится само собой — но и просто вредно, т.к. для более лучшего указания на источник ошибки начинается тестирование геттеров-сеттеров, конструкторов типа { this.param1 = param1; this.param2 = param2; } и прочие невероятно полезеные практики, столь улучшающин проценты метрик и столь тешащие сердца менеджмента.


Наоборот, геттеры и сеттеры размывают профит из за того, что тестируется 'что унутре'. С конструкторами ровно то же — тестирование 'что унутре'. Такой подход при малейшем телодвижении поломает вообще все тесты. ТО есть, сразу всё становится красным.

Скажем, для получения информации качества 'что-то не так' обычно и тесты не нужны
Отредактировано 04.01.2016 20:11 Pauel . Предыдущая версия .
Re[4]: Что и как следует покрывать юнит-тестами
От: Yoriсk  
Дата: 05.01.16 13:52
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>Самый главный принцип — красный юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а 'метод сенд актора обнуляет бехевиор если была ошибка'

Y>>Нет, не должен. Потому что это не только бесполезно — зная об ошибке в определённом сценарии ты её и так найдёшь,
I>А временем на поиски можно пренебречь?

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

I>Вообще то юнит-тесты избавляют от дебага. Классика юнит-тестирования — код теста содержит минимум кода и один-два ассерта. Отсюда ясно, что ошибка видна практически сразу, без необходимости дебага и поисков.


Ну да. Для сферической программы с абсолютным бюджетом. Юнит-тесты со 100% покрытием, полностью избавляющие от дебага и поисков сродини Снежному Человеку: все об этом говорят но никто не видел.

I>Наоборот, геттеры и сеттеры размывают профит из за того, что тестируется 'что унутре'. С конструкторами ровно то же — тестирование 'что унутре'. Такой подход при малейшем телодвижении поломает вообще все тесты. ТО есть, сразу всё становится красным.


Юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а "геттер GetX() не работает". А то эта ошибка вылезет в другом месте и, о ужас!, всё, сразу всё становится красным.
А теперь оказалось, что "наоборот".
Re[5]: Что и как следует покрывать юнит-тестами
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.01.16 06:45
Оценка:
Здравствуйте, Yoriсk, Вы писали:

Y>>>Нет, не должен. Потому что это не только бесполезно — зная об ошибке в определённом сценарии ты её и так найдёшь,

I>>А временем на поиски можно пренебречь?

Y>Да, можно.


Если так, то ты подтвердил именно то, о чем я сказал — проблема уже найдена тестом и именно поэтому дальше искать не нужно. А вариант 'чтото отвалилось' таким свойством не обладает.

I>>Вообще то юнит-тесты избавляют от дебага. Классика юнит-тестирования — код теста содержит минимум кода и один-два ассерта. Отсюда ясно, что ошибка видна практически сразу, без необходимости дебага и поисков.


Y>Ну да. Для сферической программы с абсолютным бюджетом. Юнит-тесты со 100% покрытием, полностью избавляющие от дебага и поисков сродини Снежному Человеку: все об этом говорят но никто не видел.


А при чем здесь 100% покрытие ? У меня ощущение что ты забыл или что такое юнит-тесты, или что речь про юнит-тесты.

I>>Наоборот, геттеры и сеттеры размывают профит из за того, что тестируется 'что унутре'. С конструкторами ровно то же — тестирование 'что унутре'. Такой подход при малейшем телодвижении поломает вообще все тесты. ТО есть, сразу всё становится красным.


Y>Юнит тест должен однозначно указывать на источник ошибки. Не 'что то отвалилось' а "геттер GetX() не работает". А то эта ошибка вылезет в другом месте и, о ужас!, всё, сразу всё становится красным.

Y>А теперь оказалось, что "наоборот".

Именно. 'что то отвалилось' превратилось в 'искать не нужно'.
Re[3]: Что и как следует покрывать юнит-тестами
От: fmiracle  
Дата: 06.01.16 08:30
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

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


FH>Т.е. подсовывать заранее заготовленную HTML-страницу? Если да, то тесты пройдут успешно, если даже вёрстка настоящего сайта уже давно поменялась, что вызовет некорректную работу приложения уже в процессе работы.


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

Особенно полезным это становится, если вывод сайта может быть не в виде 1 верстки, на набора разных (от количества результатов, например). Или, скажем, авито придумает вставлять в середину списка результатов какую-то свою контекстную рекламу или что-то подобное, но не всегда, а с вероятностью 5%. Как тебе проверить, что страницу с такой рекламой твой исправленный код корректно обрабатывает? Прогнать весь код 20 раз по живым результатам? Но это все равно не даст тебе уверенности, что этот шанс выпал.
Re[3]: Что и как следует покрывать юнит-тестами
От: · Великобритания  
Дата: 06.01.16 15:05
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH> Т.е. подсовывать заранее заготовленную HTML-страницу?

Про это уже написали. А я добавлю про это:

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

Пишутся ещё тесты (но это уже интеграционные, а не юнит), которые запускаются по расписанию, скажем, ежедневно, и посылают заранее определённые запросы и проверяют, что ответы соответствуют ожиданиям. Такие тесты позволят заметить внезапные изменения 3-rd party систем. Мы называем такое "compatibility tests".
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Что и как следует покрывать юнит-тестами
От: LaPerouse  
Дата: 11.01.16 11:14
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Вот например ты пилишь компонент, который кидает эвент ready когда его состояние из loading стало complete. Вопрос- как ты к этому пришел ?

I>Например было так — "мы решили что здесь будет эвент". В этом случае никаких тестов писать нет смысла.

Почему? Или вам не важно, воплощено ваше решение в жизнь или нет, и насколько качественно воплощено? Не пострадало ли при этом другое поведение и функциональность?

I>А если ты взял какую формальную модель, спроектировал на ее основе решение, то, внезапно, есть смысл проверить, обладает ли твое решение требуемыми свойствами формальной модели


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

I>Если на ровном месте появились моки, это значит что вместо проектирования у тебя кейс "а мы решили", см выше

I>Моки в юнит-тестах появиться не могут, потому или тесты не те, или проблема непонятная, или дизайн не тот.

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

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


Выявление "разных свойств" — это опять не про тесты. Тесты — это банальная защита от дурака, выявление самых типичных ошибок. Успешность выполнения тестов ничего не гарантирует, а только уменьшает количество итераций в релизном цикле и дает некоторую увереность в рефакторинге, которую, впрочем, не нужно переоценивать.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Что и как следует покрывать юнит-тестами
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.01.16 13:51
Оценка:
Здравствуйте, LaPerouse, Вы писали:

I>>Вот например ты пилишь компонент, который кидает эвент ready когда его состояние из loading стало complete. Вопрос- как ты к этому пришел ?

I>>Например было так — "мы решили что здесь будет эвент". В этом случае никаких тестов писать нет смысла.

LP>Почему? Или вам не важно, воплощено ваше решение в жизнь или нет, и насколько качественно воплощено? Не пострадало ли при этом другое поведение и функциональность?


Качество это степень соответствия требованиям. Нет требований — нет вопроса. "мы решили что здесь будет эвент" — это никакое не требование

I>>А если ты взял какую формальную модель, спроектировал на ее основе решение, то, внезапно, есть смысл проверить, обладает ли твое решение требуемыми свойствами формальной модели


LP>Формальность/неформальность имеет значение для автоматической верификации, а не для тестов. Тесты — это в первую очередь способ найти очевидные ошибки, а не гарантия соответствия модели формальным спецификациям.


На примере LIFO — свойство такого контейнера в том, что на вершине всегда последний элемент. Это не может зависеть от реализации. И тестами ты проверяешь не ошибки, а вот такое вот соответствие модели.
Т.е.
var stack = new Stack();

stack.push(x);

assert(stack.peek() == x);
assert(stack.pop()  == x);


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

LP>Как раз такие моки в юнит-тестах необходимы во всех случаях, когда данный юнит зависит от других юнитов.


Покажи пример, где, по твоему, в юнит-тесте нужен мок. А я покажу тебе кое что взамен. Идёт ?


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


LP>Выявление "разных свойств" — это опять не про тесты.


Раузмеется. Тестами ты всего лишь покрываешь основные свойства. Если ты свойство не используешь ни явно, ни косвенно, то незачем и тест для него писать. Если в контейнере ты не используешь свойство length, то совершенно не важно, будут ли тесты этого свойства зелеными или красными. Их вообще быть не должно.
Re: Что и как следует покрывать юнит-тестами
От: woah  
Дата: 12.01.16 19:11
Оценка: +1
Здравствуйте, FrozenHeart, Вы писали:


FH>Скажите, пожалуйста, всегда ли вы пишете юнит-тесты? На каких языках вы программируете и какие библиотеки используете для их написания? Делаете 100% покрытие кода тестами или "забиваете" на юнит-тестирование определённых частей проекта?


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

FH> Что при таком подходе можно тестировать? Успешность выполнения GET-реквестов и валидность данных, которые прилетают мне в ответе? Так они выполняются где-то в недрах фреймворка, я даже знать-не знаю, какие там методы вызываются и что конкретно происходит. Даже если я посмотрю в исходники и увижу, что на самом нижнем слое находится, например, urllib из стандартной библиотеки Python, то полагаться на недокументированное поведение, на мой взгляд, в данном случае глупо. Успешность записи данных в БД / Excel-файл? Первое вообще непонятно, как зафейлиться может (разве что структура таблиц не совпадает с используемой мной моделью), второе ещё ладно.


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

FH>В общем, поделитесь советами на тему того, что и как следует покрывать тестами, а что следует оставлять без покрытия. Чем вы руководствуетесь при написании юнит-тестов?


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