Comments 16
Дочитал только до контроллера, дальше желание пропало.
Опять тут у нас игра в слова началась. Unit - как бы подразумевает, что ты тестируешь некую конкретную функцианальностью в сферическом вакууме.
Другими словами, когда тестируемая функция/метод внутри себя вызывает еще сотню зависимостей, то ты их просто мокаешь, и получается тестируешь только код непосредственно этой функции. Это и называется юнит-тесты
Юнит-тест, это небольшой тест функциональности без необходимости запускать всю системы целиком.
Делать внутри юнит-теста моки или нет, зависит от объема и локализации зависимостей. Например, если для тестов нужно поднимать сервер БД, тогда логично заменить его на мок, а если в проекте используется SQLLite, то в некоторых тестах его можно и не мокать.
Речь о том что если вы для теста "используете SQLLite", то юнит-тест у вас уже не особо получится.
Потому что у вас появляется дополнительная сущность которую вы тестируете. И если тест выдаёт ошибку, то вы не знаете является ли причиной ошибки ваш "функционал" или содержание вашей SQLLite.
Если вы поднимаете сервер БД, то там уже всё немного сложнее. Если БД для каждого теста создаётся заново или каждый раз "ресетается" до одного и того же состояния, то это ещё можно считать юнит-тестом. Если нет, то у вас опять появляется дополнительная сущность.
Если БД для каждого теста создаётся заново или каждый раз "ресетается" до одного и того же состояния, то это ещё можно считать юнит-тестом.
Да, примерно это и имеется ввиду.
Потому что у вас появляется дополнительная сущность которую вы тестируете. И если тест выдаёт ошибку, то вы не знаете является ли причиной ошибки ваш "функционал" или содержание вашей SQLLite.
Конечно, название типов тестирования, это больше вопрос терминологии и соглашений конкретного проекта, хотя мне больше всего нравится считать, что юнит тесты, это тесты отдельной сущности, которые может запустить разработчик на своем компьютере автономно, тогда как интеграционные тесты, это область ответственности тестировщиков с подготовкой правильного окружения.
И в первом случае могут быть как моки вместо БД, так и непосредственное использование встроенной БД, так и оба варианта тестов одновременно (и с моками и без них). И какой тест запускать, это зависит от решаемой разработчиком задачи. Например, для регрессионного тестирования достаточно сразу запускать тесты со встроенной БД, т.к. требуется только подтверждение работоспособности, а не локализация ошибки.
Конечно, название типов тестирования, это больше вопрос терминологии
Называть вы это можете как хотите. Но весь смысл юнит-тестов в том чтобы проверять только какую-то небольшую изолированную часть функционала.
И вы либо соблюдаете это правило, либо нет.
которые может запустить разработчик на своем компьютере автономно
Я занимаюсь десктоп-разработкой. В принципе большую часть наших продуктов я могу автономно запустить на своём компьютере. И тестировать сразу всё приложение. Вручную или полностью автоматизированно. Но от этого такие тесты не становятся юнит-тестами.
Но от этого такие тесты не становятся юнит-тестами.
А как тогда вы их называете?
Тесты, в которых тестируется всё приложение целиком? "Functional tests" или "acceptance tests".
Функциональные тесты, это подтверждение работы конкретной функциональности согласно ТЗ или беклогу.
Приемочное тестирование, это тестирование функциональность продукта методом «чёрного ящика» на соответствие заданным критериям.
Описанные вами тесты не соответствуют ни одному их этих определений.
Функциональные тесты, это подтверждение работы конкретной функциональности согласно ТЗ или беклогу
Абсолютно верно. Пилится новая фича, добавляется в приложение и потом запускается всё приложение и проверяется как работает эта новая фича.
А когда готовится релиз новой версии, то запускается всё приложение и проверяется как работает всё приложение в целом. В том числе проверяется не сломалось ли что-то из "старого" функционала. Это у нас называется "acceptance tests". Но это у нас. В принципе это можно называть и как-то по другому.
При этом новая фича может состоять из кучи новых классов и методов. И юнит-тест это когда например берётся один единственный метод, изолируется и проверяется. И под "изолируется" я имею в виду что делается так, что от всех своих зависимостей он получает одни и те же данные при каждом запуске теста. И обычно это делается при помощи моков.
Описанные вами тесты не соответствуют ни одному их этих определений.
Какие "описаннве мною тесты" вы имеете в виду?
Какие "описаннве мною тесты" вы имеете в виду?
Тесты отдельного метода или класса, написанные разработчиком с использованием mock объектов.
Я тоже пишу в том числе и для десктоп приложения и практически все тесты у меня на google test framework. И там есть тесты и с моками, а есть и без них. Просто уровень изоляции может быть разный. Для одного теста обязательно нужен mock (чтобы можно было локализовать ошибку), а для теста более высокого уровня mock может и не потребоваться.
И если честно я не даже не знаю как их можно назвать, ведь ни к функциональным, ни к приемочным тестам их отнести не получится, так как я не смогу их предъявить заказчику, т.к. они выполняются на отдельной сборке, а не на законченном приложении.
Просто уровень изоляции может быть разный.
У изоляции нет уровней. Она либо есть, либо её нет. У вас есть тест. Если при любом повторе этого теста "входные данные" для юнита не меняются, то он изолирован. Если они могут измениться, то не изолирован. И это вне зависимости от того используете вы моки или нет.
И если честно я не даже не знаю как их можно назвать, ведь ни к функциональным, ни к приемочным тестам их отнести не получится
Если вы одновременно тестируете два или более "юнитов", то на мой взгляд это уже интеграционные тесты.
У изоляции нет уровней
Я писал про уровень изоляции для иерархии классов приложения. Например при нисходящем тестировании (когда вызывается интерфейс высокого уровня, а реализация нижележащих классов постепенно заменяется с MOCK реальную).
Если вы одновременно тестируете два или более "юнитов", то на мой взгляд это уже интеграционные тесты.
GTF тесты можно запустить хоть все стразу, хоть по отдельности, и это точно не интеграционные тесты, так как все "юниты" должны быть изолированы. Хотя отдельные тесты действительно можно назвать интеграционными, если внутри используются не mock объекты, а другие модули.
Но как я уже писал, в данном случае терминология не принципиальна и может зависеть как от конкретного проекта, так и от принятых соглашений (например, в моей практике был случай, когда приемочными и функциональными тестами были юнит-тесты на GTF, когда разрабатывалась низкоуровневая библиотека, а заказчиком выступал другой проект).
Здравый смысл есть, но все же идёт подмена понятий. Если замолкать вызовы то это юнит тест. Если вместо соков уже какая то реализация, то это не юнит. Есть ещё компонентные тесты, но тут сложно провести границу, где начнутся инновационные. Так что если вместо большого pgsql вы поставите SQLite, то юнит тестом это вы никак не можете назвать
Эх, видимо люди не то что "дальше контроллера перестали читать", но и самую первую строку тоже пропустили, раз такой холивар поднялся на тему "что такое юнит тест" :(
Для душнил продублирую тут основной посыл статьи, который в конце как раз отражён:
важнее писать тесты, чем заморачиваться над тем как они называются, и тем более заморачиваться над тем что должны быть только юнит-тесты.
Задача тестов, проверить реализованный функционал. Если я могу написать интеграционный/системный/приемочный, причем это будет быстрее чем написать юнит со всей кучей моков, то почему я должен писать юнит вместо подходящего теста? Поднять стенд с базой вроде ни у кого проблем не должно вызывать, либо по полноценному окружению гонять ночные тесты.
Дочитал только до контроллера, дальше желание пропало.
Опять тут у нас игра в слова началась. Unit - как бы подразумевает, что ты тестируешь некую конкретную функци
анальностью в сферическом вакууме.
@pes_loxmaty а тест контроллера почему не удовлетворяет вашим требованиям? Тестируем конкретную функциональность, изолированно, отдельно от всего проекта aka в сферическом вакууме. Не вижу тут проблем. Или проблема в нейминге "контроллер" ?
Функциональные тесты, это подтверждение работы конкретной функциональности согласно ТЗ или беклогу.
Приемочное тестирование, это тестирование функциональность продукта методом «чёрного ящика» на соответствие заданным критериям.
@rsashka А функциональные тесты разве не могут тестировать функциональность на соответствие заданным критериям методом черного ящика? Из ваших определений следует что и функциональные и приемочные тесты могут внутри содержать абсолютно идентичные конструкции :)
Кстати вопрос, а чего такое тогда системные тесты? ;)
В том числе проверяется не сломалось ли что-то из "старого" функционала. Это у нас называется "acceptance tests". Но это у нас. В принципе это можно называть и как-то по другому.
@Kanutа разве проверка "что ничего не сломалось из старого" не называется регрессионными тестами? Что ж такое, опять какая-то путаница в этих определениях :o
На всякий случай оставлю тут эту картинку. Если кто-то захочет поискать другие подобные изображения, то уверяю они будут отличаться :)
![](https://habrastorage.org/getpro/habr/upload_files/fdf/78f/b31/fdf78fb318aa01c8805e6b5cad01eac8.png)
Из ваших определений следует что и функциональные и приемочные тесты могут внутри содержать абсолютно идентичные конструкции :)
А это вообще могут быть вообще одни и те же тесты, ведь они различаются назначением, а не реализацией. И если согласовать с заказчиком использовать в качестве приемочных тестов функциональные тесты, это будет вообще высший пилотаж :-)
Или проблема в нейминге
Ага, в нейминге заголовка ))) Ведь не все тесты являются unit-тестами, что не умаляет их нужности и важности. Всякие тесты нужны.
то почему я должен писать юнит вместо подходящего теста?
Не вместо, а вместе )
Unit-тестами ты тестируешь кирпичики из которых строится приложение. Завтра ты уволишься, а вместо тебя придет новичек, который поправит какую-то функцию. Если у него завалится unit-тест то есть риск что и приложение где-то поломается - коммитить такое нельзя.
Или другой пример, завтра ты захочешь обновить либу, которая используется в твоей функции, и в новой версии всё работает иначе, тут юнит тест тебе ничего не покажет, а вот функциональный должен упасть, если теперь функция перестала выполняться.
Кароч назначение тестов разное, поэтому им и придумали разные названия. Но при этом конечно все они тесты и принцип один - убедиться что код работает так как задумывалось.
Все тесты — это юнит тесты :o