Используйте JUnit вместо TestNG — тогда вся последняя часть про Mock.reset станет просто не нужна. Прелесть JUnit в том, что он создаёт новый инстанс класса перед каждым тестом, так что мок из предыдущего теста не может повлиять на следующий. Ничего сбрасывать не нужно.
Да, в некотором роде явные: ты явно указываешь условие.
Но качественное отличие от селениумовских «explicit waits» в том, что ты не должен писать какой-то дополнительный код для этого. А главное — ты не можешь ЗАБЫТЬ прописать wait. Ты не должен тратить мыслетопливо на то, чтобы решать каждый раз: а нужно ли ожидание в каждой конкретной строчке? Ведь как известно, именно мыслетопливо — самый главный ограничительный ресурс в наше деле.
Я абсолютно согласен с тем, что код надо максимально покрывать юнит-тестами, а не UI-тестами. В том числе юнит-тестами JavaScript кода, отвечающего за отрисовку UI (Jasmine, Karma, вот это всё). Я сам всегда об этом говорю на конференциях.
Но этого недостаточно. Всё равно нужен слой UI-тестов, которые проверят, что всё приложение в целом работает. Без них можно обойтись только в сравнительно маленьких проектах, которые легко прокликать руками после каждого изменения.
P.S. Кстати, вы путаете одну вещь. Конкретно вот это утверждение неверно:
> Не эмулируйте сервисы вообще, обходитесь в тестах без них.
Без них в тестах нельзя. Даже в юнит-тестах всё равно нужно делать эмуляторы зависимостей (моки, стабы и т.п.), просто они делаются по-другому. И гораздо дешевле.
P.P.S. Описанный кейс с платёжным агрегатором разумный, но в моей практике это происходит по-другому. Обычно, когда агрегатор падает в тестовой среде, нам говорят «да, в тестовой среде мы его обновляем, это займёт неделю. Но в продакшине всё точно работает.» Или «на тестовом сервере просто железо слабоватое, и там сейчас другая команда нагрузку запустила на несколько часов». А ты не можешь ждать, тебе надо релизиться. Вот в такой ситуации разумно свой функционал тестировать на эмуляторах, а с реальным сервисом как-то отдельно потом проверить (да хоть даже вручную), когда все свои ошибки уже точно исправлены.
Селенидрвские ожидания — и не implicit, и не explicit. Можно сказать, они взяли лучшее от обоих видов. На implicit wait они похоже тем, что их не надо как-то специально вызывать — они срабатывают автоматически всегда. А на explicit wait похожи тем, что ждут именно того, что тебе нужно.
И да, api для их вызова в селениде гораздо компактнее.
Если вкратце — implicit wait умеет ждать только наступления одного события: что элемент появится в DOM. Селенидовские ожидания могут ждать чего угодно (например, что элемент исчезнет из DOM).
s-kozlov Перед тем как фейспалмить, вы немножко задумайтесь, к чему я клоню. Я говорю, что ваша логика не работает. Все ваши доводы против TDD точно так же распространяются и на каску. Но вот сюрприз — она общепризнанный стандарт. Значит, ваши доводы не работают. Либо каска стала общепризнанным стандартом без всяких доказательств, а просто на основании многолетнего опыта. Так же как у нас TDD.
Fesor Про BDD я, конечно, знаю, и отношусь к нему очень скептически.
Это красивая идея, но на практике она не работает. Никогда бизнес «стейкхолдеры» не пишут эти спеки вместе с разработчиками и QA. В итоге этот «геркин» привносит новые проблемы, а обещания не выполняет.
Но даже если предположить, что BDD отлично работает, интеграционные и т.п. тесты никогда не заменят юнит-тестов. Поэтому BDD может существовать, но не заменит TDD.
PS. Каким таким волшебным образом использование языка геркин сделает интеграционные тесты очень быстрыми?
s-kozlov Вы упорно не замечаете сходства. По вашей логике и каска — всего лишь один из инструментов. Нигде нет доказательств, что он лучший. И наконец, ходить в каске — сюрприз-сюрприз — противоестественно!
Fesor Ну да, идея примерно та же. Заставить заранее продумать детали -> получить меньше багов.
Было бы интересно взглянуть, как примерно выглядят ваши критерии приёмки. Это какие-то требования в текстовом виде?
Но подозреваю, что они всё равно не могут быть на таком же уровне детализации, как юнит-тесты. А значит, детали будут потеряны, и снова баги.
А я вот усматриваю фанатизм в вашем стремлении во что бы то ни стало обвинить меня в фанатизме. :)
Чем тогда этот «фанатизм» отличается от фанатизма прораба, который заставляет всех ходить по стройке в каске? Каждый, кто ходит по стройке, тоже может сказать, что он мастер, что умеет ходить аккуратно, у него своя техника…
P.S. Вы таки упорно не замечаете самого важного: для нас главное вовсе не методология, а делать продукт быстро и качественно. То есть те самые пулевые отверстия.
P.P.S. Статью про IDEA/Eclipse вы, очевидно, читали очень невнимательно. Там в самом первом предложении сказано: «IDEA лучше как IDE для Java». А вы мне говорите — «когда выходит новый язык». При чём тут новый язык? Я же говорю — для Java. А в конце статьи я писал, что есть целый перечень ситуаций, в которых Eclipse вполне может быть лучше. Внимательнее надо быть, товарищи!
Я согласен, слово «гарантирует» здесь не совсем корректно. Впрочем, полной гарантии не даёт вообще ничто на свете, так что споры о гарантиях мне кажутся бесполезными.
Ок, TDD не даёт полной гарантии, но даёт высокую степень уверенности.
Вы забываете, что TDD не равно просто «зелёный тест». Да, сам по себе зелёный тест не говорит вообще ни о чём. Но зелёный тест, который до изменения кода был красным — это уже кое-что. Именно поэтому и важно писать тесты до кода.
s-kozlov Нет, не фанатизм. Это выводы, основанные на многолетнем опыте. Я ведь много лет работал и так, и так. Точно так же как с IDEA и Eclipse. Там, кстати, я тоже приводил совершенно понятные логичные доводы. При чём тут фанатизм?
Так TDD для того и нужен, чтобы тесты не надо было тестировать!
Именно эта последовательность: красный тест — код — зелёный тест — и гарантирует, что тест правильный.
Согласен. Достаточно лишь продумать.
Но в том-то и проблема — как этого добиться? Стабильно. Чтобы не было такого, что сегодня продумал, а завтра не продумал — ну настроение не то, не срослось. Лекарства лучше, чем TDD (+парное программирование), человечеству пока неизвестно.
Ох, и откуда вы этих стереотипов про эффективных менеджеров набрались?
Я анекдоты про них слышал, а в жизни никогда не видел.
Ну конечно же, для самое главное — это качественный продукт в срок и поддерживаемый код. Только как этого достичь? У нас собрались единомышленники, которые считают, что TDD (ну и ряд других практик) — самый эффективный способ. Эффективные менеджеры тут не при чём.
P.S. Про целеустремлённых людей это был лёгкий троллинг, конечно.
Понятно, что не пошёл бы. Таких на самом деле большинство. Ну и хорошо, нам ведь нужны только целеустремлённые люди.
На самом деле у нас свобод гораздо больше, чем в других конторах. У нас нет «архитектора» или «тимлида», который указывает тебе, что делать. Ты можешь выбирать проект, фреймворки, даже языки программирования. И IDE тоже. Это то, о чём большинство людей в IT даже не мечтает.
… Только их надо выбрать вместе с напарником. И это ведь хорошо, не находите? Иначе слишком легко сделать неправильный выбор в одиночку.
s-kozlov Всё верно, такой способ мышления кажется противоестественным. Не только вам, но и мне, и всем адептам TDD.
В этом вся суть: надо сломать свой типичный ход мышления. Надо заставить себя действовать «противоестественно». Надо выйти из зоны комфорта. Надо, потому что это того стоит.
P.S. Чешем, ещё как чешем. Мало TDD, мы ещё и практикуем парное программирование. То есть сидеть одному и шпарить «по-своему» по-любому не получится. Мы об этом рассказываем на собеседовании (да собственно, это и на сайте написано), поэтому те, кто не готов меняться и учиться новому, просто изначально не приходят к нам на работу.
Отключить эти ворнинги, как минимум в тестах.
Используйте JUnit вместо TestNG — тогда вся последняя часть про Mock.reset станет просто не нужна. Прелесть JUnit в том, что он создаёт новый инстанс класса перед каждым тестом, так что мок из предыдущего теста не может повлиять на следующий. Ничего сбрасывать не нужно.
Но качественное отличие от селениумовских «explicit waits» в том, что ты не должен писать какой-то дополнительный код для этого. А главное — ты не можешь ЗАБЫТЬ прописать wait. Ты не должен тратить мыслетопливо на то, чтобы решать каждый раз: а нужно ли ожидание в каждой конкретной строчке? Ведь как известно, именно мыслетопливо — самый главный ограничительный ресурс в наше деле.
Но этого недостаточно. Всё равно нужен слой UI-тестов, которые проверят, что всё приложение в целом работает. Без них можно обойтись только в сравнительно маленьких проектах, которые легко прокликать руками после каждого изменения.
P.S. Кстати, вы путаете одну вещь. Конкретно вот это утверждение неверно:
> Не эмулируйте сервисы вообще, обходитесь в тестах без них.
Без них в тестах нельзя. Даже в юнит-тестах всё равно нужно делать эмуляторы зависимостей (моки, стабы и т.п.), просто они делаются по-другому. И гораздо дешевле.
P.P.S. Описанный кейс с платёжным агрегатором разумный, но в моей практике это происходит по-другому. Обычно, когда агрегатор падает в тестовой среде, нам говорят «да, в тестовой среде мы его обновляем, это займёт неделю. Но в продакшине всё точно работает.» Или «на тестовом сервере просто железо слабоватое, и там сейчас другая команда нагрузку запустила на несколько часов». А ты не можешь ждать, тебе надо релизиться. Вот в такой ситуации разумно свой функционал тестировать на эмуляторах, а с реальным сервисом как-то отдельно потом проверить (да хоть даже вручную), когда все свои ошибки уже точно исправлены.
Ну блин, вы уж потрудитесь статью-то прочитать, которую комментируете. :)
Там же всё есть: https://hsto.org/webt/gq/x8/uq/gqx8uq3gjj6wudrx0n3uajntzdy.jpeg
Селенидрвские ожидания — и не implicit, и не explicit. Можно сказать, они взяли лучшее от обоих видов. На implicit wait они похоже тем, что их не надо как-то специально вызывать — они срабатывают автоматически всегда. А на explicit wait похожи тем, что ждут именно того, что тебе нужно.
И да, api для их вызова в селениде гораздо компактнее.
Если вкратце — implicit wait умеет ждать только наступления одного события: что элемент появится в DOM. Селенидовские ожидания могут ждать чего угодно (например, что элемент исчезнет из DOM).
Это красивая идея, но на практике она не работает. Никогда бизнес «стейкхолдеры» не пишут эти спеки вместе с разработчиками и QA. В итоге этот «геркин» привносит новые проблемы, а обещания не выполняет.
Но даже если предположить, что BDD отлично работает, интеграционные и т.п. тесты никогда не заменят юнит-тестов. Поэтому BDD может существовать, но не заменит TDD.
PS. Каким таким волшебным образом использование языка геркин сделает интеграционные тесты очень быстрыми?
Значит, TDD — это правила, написанные кровью.
Было бы интересно взглянуть, как примерно выглядят ваши критерии приёмки. Это какие-то требования в текстовом виде?
Но подозреваю, что они всё равно не могут быть на таком же уровне детализации, как юнит-тесты. А значит, детали будут потеряны, и снова баги.
Чем тогда этот «фанатизм» отличается от фанатизма прораба, который заставляет всех ходить по стройке в каске? Каждый, кто ходит по стройке, тоже может сказать, что он мастер, что умеет ходить аккуратно, у него своя техника…
P.S. Вы таки упорно не замечаете самого важного: для нас главное вовсе не методология, а делать продукт быстро и качественно. То есть те самые пулевые отверстия.
P.P.S. Статью про IDEA/Eclipse вы, очевидно, читали очень невнимательно. Там в самом первом предложении сказано: «IDEA лучше как IDE для Java». А вы мне говорите — «когда выходит новый язык». При чём тут новый язык? Я же говорю — для Java. А в конце статьи я писал, что есть целый перечень ситуаций, в которых Eclipse вполне может быть лучше. Внимательнее надо быть, товарищи!
Ок, TDD не даёт полной гарантии, но даёт высокую степень уверенности.
Вы забываете, что TDD не равно просто «зелёный тест». Да, сам по себе зелёный тест не говорит вообще ни о чём. Но зелёный тест, который до изменения кода был красным — это уже кое-что. Именно поэтому и важно писать тесты до кода.
Именно эта последовательность: красный тест — код — зелёный тест — и гарантирует, что тест правильный.
Но в том-то и проблема — как этого добиться? Стабильно. Чтобы не было такого, что сегодня продумал, а завтра не продумал — ну настроение не то, не срослось. Лекарства лучше, чем TDD (+парное программирование), человечеству пока неизвестно.
Я анекдоты про них слышал, а в жизни никогда не видел.
Ну конечно же, для самое главное — это качественный продукт в срок и поддерживаемый код. Только как этого достичь? У нас собрались единомышленники, которые считают, что TDD (ну и ряд других практик) — самый эффективный способ. Эффективные менеджеры тут не при чём.
P.S. Про целеустремлённых людей это был лёгкий троллинг, конечно.
На самом деле у нас свобод гораздо больше, чем в других конторах. У нас нет «архитектора» или «тимлида», который указывает тебе, что делать. Ты можешь выбирать проект, фреймворки, даже языки программирования. И IDE тоже. Это то, о чём большинство людей в IT даже не мечтает.
… Только их надо выбрать вместе с напарником. И это ведь хорошо, не находите? Иначе слишком легко сделать неправильный выбор в одиночку.
В этом вся суть: надо сломать свой типичный ход мышления. Надо заставить себя действовать «противоестественно». Надо выйти из зоны комфорта. Надо, потому что это того стоит.
P.S. Чешем, ещё как чешем. Мало TDD, мы ещё и практикуем парное программирование. То есть сидеть одному и шпарить «по-своему» по-любому не получится. Мы об этом рассказываем на собеседовании (да собственно, это и на сайте написано), поэтому те, кто не готов меняться и учиться новому, просто изначально не приходят к нам на работу.