Email or username:

Password:

Forgot your password?
Tech Thread

Согласно TDD я должен написать сначала спецификацию, затем -- тесты, и только потом -- код. Но каким образом я могу написать тесты для функций, которые вызывают системные функции?

Ясно, что их нужно изолировать: для этого используются mock'и, stub'ы и иже с ними. Однако для этого я должен заранее знать, какие функции будут использоваться в реализации. Но это знать невозможно, поскольку сначала идут тесты! Более того, странно опираться при тестировании на реализацию, а не спецификацию: реализация может поменяться спустя некоторое время, а сигнатура тестируемой функции должна быть неизменной.

К тому же, сами вызываемые системные функции могут варьироваться: на Linux для определённой цели может использоваться epoll, а в FreeBSD для той же цели kqueue. Как написать тесты, чтобы их не пришлось бы переписывать для каждой платформы в отдельности? Хотелось бы написать их написать один раз, опираясь на спецификацию (которая пишется тоже один раз) и забыть о них. @tech by @devadideva

14 comments
⚛️Revertron

TDD отличная штука на бумаге, и в сферическом вакууме, когда ты знаешь свой будущий продукт до последней функции. А такое не бывает в этой вселенной.

@tech
@devadideva

devadideva

@Revertron@zhub.link @tech@mastodon.ml Что же тогда использовать? Как я могу гарантировать пользователю, что функции работают как надо?

⚛️Revertron

@devadideva @tech Пользователю нужно уже интеграционное тестирование.

А обычные тесты функций нужны разработчикам чтобы после рефакторинга сразу найти то, что поломалось.

devadideva

@Revertron@zhub.link @tech@mastodon.ml Ага, понятно. Может тогда мне и не нужны unit-тесты, а будет достаточно только функциональных?.. Хочется сделать правильно, но, как всегда, не получается... Есть какие-то чёткие границы: вот тут вот нужен обычный тест, а вот тут -- интеграционный?

⚛️Revertron

@devadideva @tech Обычно нужны все виды тестов :)
Но не везде их вообще возможно запрогать 😕

devadideva

@Revertron@zhub.link @tech@mastodon.ml Я один все виды не потяну... Ну что же, спасибо за отклик! Перфекционизм, по всей видимости, опять вредит мне.

⚛️Revertron

@devadideva @tech Я тоже в своём роде перфекционист. Но важно какие параметры софта ты считаешь более важными.
Если для тестируемости надо сотворить монстра, то это точно не ко мне.

[DATA EXPUNGED]
Alex

@devadideva

>Но каким образом я могу написать тесты для функций, которые вызывают системные функции?

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

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

devadideva

@alex@lor.sh Хорошо, посмотрю; благодарю за совет!

vCarabis

@tech
Спецификации должны чётко описывать на каком наборе входных параметров какой результат ожидается. Этого вполне достаточно чтобы написать тест. Что происходит там внутри не должно влиять на это.

Другой вопрос что далеко не все функции имеет смысл тестировать. Например функции с тривиальной логикой. Ну и как сказали выше, если писать код с прицелом на тесты, моки и т.д., работать это все будет не очень хорошо, да и поддержка такого кода может быть слишком трудоемка.
@devadideva

devadideva

@vCarabis@mastodon.social @tech@mastodon.ml Так в том то и дело, что поведение функции не всегда однозначно определяется входными параметрами! Но это уже было обсуждено. Спасибо за отклик!

vCarabis

@devadideva
Возможно тогда стоит пересмотреть дизайн самой функции и все что влияет на её поведение вынести за её пределы и сделать входными параметрами. Если таких параметров много будет, то я бы задумался о декомпозиции такой функции.
@tech

devadideva

@vCarabis@mastodon.social @tech@mastodon.ml В общем то я с Вами согласен (привет тем, кто написал getopt и иже с ним!), но не во всех случаях это возможно: например функция socket(); структура сокета аллоцируется системой, а в ручки попадает только дескриптор. Вы бы как переписали эту системную функцию, а? Отдавали бы структуру сокета пользователю? Это неудачное решение.

vCarabis

@devadideva
Если бы мне надо было проверить правильность заполнения структуры функцией socket(), я бы не писал тест для этой функции совсем :)

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

Эти функции уже можно написать однозначно вычисляющими результат. Главное не сильно увлечься этим делом и не загонять каждую строку кода в отдельную функцию
@tech

@devadideva
Если бы мне надо было проверить правильность заполнения структуры функцией socket(), я бы не писал тест для этой функции совсем :)

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

Go Up