наконец вы научитесь писать тесты я уже не хочу всякий мусор в базу писать я спрашивал ребят что доставляет вам боль что вы не понимаете в чем хотите разобраться а мы сейчас в каком слое работаем нам прислали нормальные данные а не какую-то дрянь то что надо начинать с простого надо минимальными средствами получить какие-то максимальные гарантии возможно просто ваша команда не хочет писать тесты аргументирует тем что ну это не надо они могут легко сломать ваш функционал это уже чуть сложнее хотим начать самого простенького всем привет с вами саня я старший разработчик в азот и вектор в навыках данное видео я хочу посвятить в воду в тестировании тому как вообще писать тесты и зачем это нужно идея мне пришла после общения с разработчиками начинающего уровня и даже уже с метлами с некоторым опытом я спрашивал ребят что доставляет вам боль что вы не понимаете в чем хотите разобраться у кого-то были проблемы с карм skunk anansie у кого-то проблемы с интерфейсами системы типов с указателями многих проблем и оказались с тестированием и тестирование одно связано с до композиций и архитектуры приложения поэтому непонимание как тестировать говорит еще и о том что вы пока не очень понимаете как собственно декомпозировать код как разделять его и об этом мы поговорим вы сможете в этом видео узнать какие виды тестов бывают какие у нас есть свои приложения мы поговорим об этом немножко поговорим о том какие гарантии мы получаем когда тестируем определенные слои приложения определенными тестами ведь мы время тратим но написание тестов мы не просто так это делаем и какие-то гарантии хотим получить что код даже больше не сломают хотим понимать какой кусок приложение теперь надежно работает ну а за какой и мы все еще не можем ручаться потому что тестом его не покрыли наконец вы научитесь писать тесты потому что это самое главное можно много говорить но главное чтобы умели их написать и наш кот было классным и защищенным вы поймете наверное если у вас протекает абстракции вы увидите теперь своем коде что они протекают надо их починить потому что возможно вы попали в команду где все используют глобальные переменные окружения прямо в конструкторах и даже если вы захотите протестировать этот код о это будет сделать не так уж и просто возможно просто ваша команда не хочет писать тесты аргументирует тем что ну это не надо они могут легко сломать ваш функционал возможно видео опять таки даст вам несколько доводов ну почему это нужно писать возможно вы начнете и затяните всех остальных и будете радостно все тесты а если вы их просто копипастите от опыта коллег но не очень понимаете как они работают то видео даст вам какое-то понимание а что же мы собственно делаем я еще раз подчеркну очень важно что мы не только разбираемся здесь тестах мы все-таки еще говорим и о слоях на которых данные теста пишутся вот давайте-ка я немножечко теория а потом приступим к практике есть такое понятие как тестовая пирамида вот оно перед вами в самом простом виде здесь мы в основании имеем вот так давайте здесь мы в основании имеем юнит-тесты поверх них слой интеграционных тестов и сверху инту эн тесты что это за слои что они значит как видите в основании наибольшее количество юнитов юниты это самый простой тест который не имеет каких-то зависимостей этот тест отдельного метода нашего объекта отдельные функции какое-нибудь мы даем какие-то данные на вход получаем какие-то данные на выход собственно написать такой тасс довольно просто и они очень дешевые поэтому нам следует обмазываться этими тестами как можно больше до растить покрытие тестовой именно здесь при этом надо понимать какие гарантии дают нам эти тесты они говорят что ну вот этот метод работает правильно и вот этот метод работает правильно но они не могут нам гарантировать что правильно работает например весь api road какой то что я иду в некоторую ручку создаю некий заказ нету гарантии что там всеми дул в валидаторы походы в базу данных от работают правильно и нам соберется правильный ответ нет за это уже отвечают интеграционные тесты их множество уровней кто-то включать туда модульное тестирование кто-то не включает кто-то включает туда api тестирование кто-то называет от тестирование отдельным уровнем это все как у вас в компании леди договорились так и считается но в целом можно все это отнести к интеграционному тестированию то есть интеграция каких-то двух зависимостей и или это какие-то разные классы или это какая-то другая зависимость например хранилища данных эскулюс гель или какой-то брокер сообщений или другой веб-сервис до микро сей раз монолит в которые вы ходите то есть тест в котором уже есть какая-то зависимость его сложнее написать его сложнее поддерживать потому что зависимость это может отвалиться тем не менее он позволяет вам подсветить какой-то вот большой путь какой-то иногда юзер стори что она вот выполняется корректно наконец сверху пирамиды у нас находится и toefl test и это самые дорогие тесты и дорого писать и поддерживать но критические участки функционал и иногда ими обкладывают например если у вас интернет магазин вы хотите убедиться что если вы нажали сделать заказ то у вас сработает и frontend отправиться запрос в бэг-энд bag and service сходит еще в 3 сервиса они еще куда-то создадутся записи во всех низлежащие хранящих данных брокеры сообщения все разошлют модификации разрастется и так далее очень дорогие тесты поддерживать их дорого еще у нас тестовое окружении всегда отличается от боевого поэтому полной гарантии мы все равно не получим но тем не менее такие тесты вот в критических участках функционала бывают важны мы начнем с июне тестов мы не будем забегать вперед то есть надо начинать с простого надо минимальными средствами получить какие-то максимальные гарантии на понимать что все-таки юнит нам не гарантировать то что у нас наши api и методы будут отрабатывать правильно за написанием unit тестов мы таких гарантий не получим если нас какие-то зависимости сервисе у нас есть у нас например в примере который я приготовил будет база данных так давайте посмотрим у нас это цитата из чистой архитектуры если вам интересно что это если не знаете напишите в комментариях сделаем видео по теме вот здесь представлена съемка со слоями приложения и когда мы что-то тестируем да и вообще когда мы пишем код нам следует хорошо понимать а мы сейчас в каком слое работаем entities это просто некоторые до сущности который мы что-то складываем и передаем их между слоями или внутри слоев между разными классами они могут иметь какое-то свое поведение и space это собственно бизнес-логика контроллеры идей твои это уровень где мы принимаем входящие какие-нибудь запроса и перекладываем их во внутренней структуры данных вы лидируем их и так далее ну и наконец есть уровень устроив устройств баз данных и внешних интерфейсов и так далее сейчас мы наверное хотим заострить наше внимание на уровне и вот зеленого красным на уровне контроллеров гей тв и на уровне из кейсов мы сейчас говорим о веб-сервисе такой у нас пример будет соответственно вот как-то на придать какой-то запрос это уровень gate vs надо его права лидировать у нас не будет какого-то медали отдельного ну вот мы долго это где-то здесь же нам надо его права лидировать нам нужно white и превратите некие структуры данных потом обратных вернуть аю space это действительно в базу сходить циклами какими-нибудь оба идти полученный ответ данные как-то нам опять друг на друга и так далее и вот если мы пишем юнит-тесты наги твой то надо понимать что мы проверяем мы валидацию например проверяем входящего сообщения или это уже не unit-тест или это может быть интеграционный api тест и он пойдет в ews кейс вот в этот в красный круг или же мы тестируем не space и опять таки это может быть какой-то unit-тест с мокрыми зависимостями нас фальшивыми и он просто говорит что если зависимости от работали хорошо то тогда у нас вернется корректный ответ мы не проверяем весь обе путь мы проверяем только часть его это дешевле но и гарантию нас более слабые я здесь набросал небольшой микро сервис который просто сохраняет и отдает некоторые заказы ордера и ещё там есть яха ручка которая просто строку нашего запросам отдает собственного за двумя уровнями мы будем работать гей твайлайт это mapping запросов и наук и валидации того что нам прислали нормальные данные а не какую-то дрянь и бизнес-логика собственною space и где полезная работа происходит и подними ещё в репозитории которыми я от базы данных абстрагировался не хотим сейчас не работать не хотим сейчас писать на пиджи x тесты это уже чуть сложнее хотим начать самого простенького вот резистор для нас какой-то на самый низкий старт давайте начнем писать какие-нибудь тестики которые дадут пользу при этом в них не будет никаких зависимостей это самое простое самая быстрая и уже принесет нам какую-то пользу только нужно понять где мы можем написать такие простые и дешевые тесты но сейчас разберемся и второе это unit тесты и которых уже есть некоторая зависимость и ее но на подделать например ну недостающую базу данных мы будем ходить в тестах мы можем там ведь вся и в git лобби где-нибудь куда мы загружаем наш попал request поднимать различные тестовое окружения мы сейчас туда не идем это пока сложно в этом видео хотим как-то просто сделал хотим начать так должны были мы переместиться в код а я должен был наверх переехать кажется что все так и произошло отлично давайте быстренько разберем слой инициализации нашего приложения получаем некоторые лагер регистрируем метрики регистрируем мы их замечу глобальным у этого есть свои последствия начнем писать тесты тоже с этим столкнемся зависимость глобально не очень удобно для тестирования лучше бы нам это как-то передать было как зависимость но мы уже совершили такой выбор потом поправим получаем конфигурационный файл передаём его в хендлер где регистрируются зависимости и регистрируется роутинг и запускаем лисин surf собственно крутимся на выбранном порту пока не пойдем давайте запустим наш котик вот у нас есть ручка эхо каире string там отдается надеюсь вам все видно увеличу немножко можем сохранить заказик мы передаем заказики джейсон кую зайди пойман type и этим sata что мы купили у них есть одессе чко стоимость и скидочка один discount передаем секса сок статус 200 создали давайте еще один создадим отлично давайте попробуем их получить так кстати создали новые мне там станьте еще остались мы создали 2324 у меня остались 2122 я тут игрался до этого здорово значит можно попросить даже двадцать один двадцать два двадцать три двадцать четыре верни нам все заказики вот он обед в двадцать один двадцать два двадцать три двадцать четыре до можем попросить поменьше нам отдать только 24 вот у нас тогда один заказик вроде бы наша отписка работает все здорово но не совсем во первых есть тут пара багов во вторых кое-что в слоях не при абстракции протекают друг в друга в третьих опечатку это у довольно легко сломать нос смотрите я написал некоторых слой валидации если я user 10 пришлите мне же валидация не проходит bad request если я не правильный pm этой в виду у меня карт и уэллет ведь тоже то есть у меня есть уже некоторые валидация отведите не совсем легкомысленно подошел я уже не хочу всякий мусор в базу писать я хочу это на этапе парсинг обработки запроса как-то отсеивать то есть у нас вот мы хотим на зеленом уровне не переходя в ews кейс плохие запросы отбрасывать возможно вас приложение этим занимается middle в или какой-то отдельный слой выведен у меня пока ничего этого нет я покажу как у нас все просто вот давайте перейдем в роутер tags регистрируем наши хинду функции и создаем здесь узкие сельский совет и уже слой бизнес-логики так вот давайте посмотрим что у нас делают функции cry i get в хендлер ах они получают у некоторых теперь и квест перекладывают park ji сенку перекладывают ее в нашу до того же чеку в ордер ян го лидирует запрос если все хорошо то вызывают уже юз кейс говорят бизнес-логика красный слой пожалуйста обработаем не все и отлично пишут хороший статус если все отлично пишут плохой статус если какие-то проблемы теперь посмотрим get в дети тоже мы получаем request партия и в структуру вы лидируете и и уже передаем ее опять таки на уровень из кейса говорим дай нам пожалуйста данные и диски если мы их получили мы их отправляем пользователю обратно ой как здорово вот валидации у нас здесь прям вот зашита на этом уровне все совсем просто то есть если мы это будем как-то развивать может абстрагируемся валидации она здесь проверяется the user айди не 0 что пойман type он у нас доступен вот у нас их два входят в доступные значения что какие-то товары переданы страны если мы оформили заказ ничего не купили что у этого должна быть одиночка не 0 начать смысла не имеет ну и стоимость 0 тоже это очень странно а вот discount скидка 0 может быть поэтому и там его лидировать нибудь так и давайте посмотрим собственный у space в ews кейси у нас здесь мы сохраняем вызываемой по истории говорим сохрани пожалуйста ордер и вот у нас есть счетчики мы хотим знать сколько у нас аккаунт сколько у нас всего был вызван раз данный метод если ошибка то счётчик об ошибке пожалуйста увеличь если все успешно то счетчик успешных заказов пожалуйста увеличь если мы хотим получить списочек то у нас здесь опять-таки метрика которые ошибочка при получении заказов общий счетчик заказов и получение за кажутся access общее количество заказов тоже увеличивается я это все делал даже дом в консольку пишу да вот мы когда пишем здесь если мы дошли до юз кейса то вот метрика ок инкремента ведь увеличивается 4-бет vardus запросов og так а как вы видите кстати ошибка здесь не появилась почему она не появилась например сделаем сын ордер и здесь ошибочку user айди не прошла validation почему то здесь ничего не получилось потому что метрики я регистрирую views кейси и зарегистрируй армении х использую с кейси вот здесь вот никаких метрик нет на уровне хендлера на уровне контроллера гид вы видите америке уже внутри получается валидация не прошла метрика в этом не тот не очень хорошо сделано а если давайте я попробую у меня идише чик несколько в базе я попробую с очень большой одесской товар сделать у меня уже ошибка от подушечки это уже - кей зашли прошли кбд она не смогла ничего записать видите у нас send or cold один стал то есть эти метрики тоже получается мы на одном слое разместили на другом нет неправильно сделали надо будет поправить но сейчас мы этим заниматься конечно не будет так итак а в успехе то у нас что но twice кейс мир сказал что он сохраняет все понятно получает из репозитория данные и еще у каждого у каждого этом и есть некоторая цена и некоторая скидка мы хотим пройтись просуммировать их и записать в наш заказ сказать ну не хранить отдельным полем вот эта общую сумму и общую скидку вот не хотим это где нормализованы хранить хотим в цикле здесь пройтись мы все это складываем перекладываем сlassic из хэш-таблицы и обдаем результате ok то есть какая то вот еще полезная обработку нас есть не просто мы сходили в баску давайте посмотрим вот мы делаем get ardors все ли у нас хорошо вроде бы написали так слегонца но видите у нас есть тут e-mount own то это все должно про суммироваться 10000 2 discount это мало должно все про суммироваться а у нас здесь по нулям опачки если бы написали тест и проверены такого не было потому что вот в этом цикле мы получаем а это мы не по указателю с хэш-таблицы складываем сингл ордер сумму но это так не работает к сожалению нужно будет этот баг поправили нужно будет даже позаботиться чтобы наш коллега случайно это не сломал при этом если мы захотим протестировать данный эскиз тоже нас возникнут проблемы видите мы передаем в него конфиг а он уже создает внутри себя репозиторий который внутри себя создает пул по сгрыз а и это не очень правильно потому что сейчас мы просто не сможем создать наш эскиз у нас в тесте если настоящая база данных нет просто не получится создать автор репозитории там умрём на свое здесь прям написал дпф ругнулся ios просто программа завершится то есть нам нужен постоянный connect базой данных живая база чтобы все это как проверять работоспособность это никуда не годится это как раз вот такая зависимость которая прибито гвоздями на мой нужно поднять бы наверх вот здесь где-то разместить тогда весь код будет не так сильно связан мы сможем туда какой-нибудь двойник опрокинуть и получить ненастоящую базу данных которые будут действовать как настоящие это мы чуть позже сделаем но вначале вначале хочется как я сказал написать какие-то unit тесты которые не требуют зависимости и на самом деле у нас есть такой небольшой слой это это это как раз таки слой валидации вот мы написали api ручку и вот у нас здесь валидация что-то юзера иди должен быть такой ты так далее это можно очень просто взять и удалить эта проблема так быть не должно как нам защитить этот код от очумелых ручек другого разработчика и лет нас самих кто-нибудь возьмет будет мешать ками ты случайно потеряет эту функцию ну и так далее всякое возможно возьмет там не знаю вернет вместо ошибки нал тоже будет поведение не на которые мы закладывались как нам быть ну давайте напишем простенький тест навредит request писать его нам буквально 5-10 минут и мы уже получим защиту нашей валидации для начала давайте проверим что сейчас-то валидация работает если мы попробуем заставить плохой ордер не получится если мы попробуем какой-то gayman type плохой не получится если мы передадим ради жку не получится ничего если мы не передадим цену тоже все свои лица но и наконец если мы просто а это мы не передадим тоже провал то есть нам нужно сейчас защитить вода слой валидации написать маленький тест который буквально эту функцию будет во лидирующую проверять 20 строчек и уже у нас есть надежность что дрянь всякая в базу не попадет это очень дешево давайте этим займемся и так чтобы протестировать валидацию давайте создадим рядом скорее файлик greatest удалить пожалуйста и вот здесь людей чтобы go понял что это этот тестовый штука которая нужно запускать надо передать туда testing ты еще буду нас импортировался вот теперь go будет знать что это тест его нужно запустить если мы напишем консоли год тест укажем путь эти функции начнет прогонять вот и даёшь к нам сразу подсказывает я понимаю что это тест видите пустой тест все отлично так так мы сделаем нам нужно проверить вот эти вот все сценарии все эти iv чеки должны выполнить у нас успешно никаких зависимости нету очень хорошо поэтому создаем создадим хендлер создадим то что мы в него передаем им в хендлер надо знать что передать этот им получить какую-то ошибку и что-то с ней сделать ордер у нас должен быть напомню хороший без ошибок поэтому мы сейчас передаем хорошие данные мы сейчас тестируем успешный сценарий потом будем тестировать неуспешны что будет если мы всякую дрянь передадим отойди должен быть 1 м а он тоже должен быть больше 0 вот мы получим получили ошибку как проверить теперь что все хорошо вот ошибка на ошибке нету надо какие-то утверждения сделаться мы можем сами сказать если ошибка то пожалуйста тег напиши нам в лоб и прекрати выполнения теста это просто птф не должны передавать в или дар дар москва а у нас тут ошибка внезапно коридор дерма спас запустим это дело все ok давайте теперь давайте теперь представим что вот мы взяли так вот сломали этот код то есть кожа не проходит здесь ошибка не надо пока оставим так но ты хотел мне не очень нравится есть два пакета от тесте фая acer 3 ква я они мне нравится намного больше предоставляет множество специализированных проверок чтобы мыло турками не писали все это их не соответствует assert просто делает какую-то проверку идет дальше ругается если что-то не работает 3 club прекращает выполнение теста мне этот подход близок я значит хочу убедиться что у нас нету ошибки но можно сказать new до ошибка должна быть на а вот мы можем запустить это не проходит тест если user1 all user 10 починили под всякий но не у не очень хорошо потому что мы ждем не просто на мы ждем что это некоторая ошибка будет ошибка которая под этим интерфейса ничего нет но error давайте сделаем вот такая проверка есть мы прям говорим не должно быть ошибки об тест проходит но и опять таки давайте его поломаем немножечко все тест уже не проходит говорит я ожидал как раз не ожидал говорит что rs вот такой рисита на террор но здесь чем должно быть здорово протестировали хороший сценарий ну тут все просто теперь давайте протестируем сценарий немножечко более сломанный нам нужно все наши сценарии посмотреть когда у нас user евгений дод здесь мы починим конечно все и создали вторую функцию тест были do it rock давайте для начала сюз ради разберемся а потом замотаем все это в циклы сделаем так называемой табличные тесты чтобы не копипастить 10 раз создания всего мы вначале объявим массив структур капотом и их в цикле прогоним все наш тест кейсов tags сначала вот так вот сделаем в тупую один сценарий проверяем user айди у нас 0 остальное вообще передавать не будем ожидаем что здесь есть ошибка окей успешно у нас ошибка мы вот здесь вот упали но есть нюанс можно взять вот так вот удалить этот код ошибка все равно есть потому что теперь у нас нету поймут toyfa мы же ничего не указали там пустая строка мы проверку удалили теста не сломались не этот меня не устраивает давайте как-то поправил мы хотим более специализировано проверить что у нас вот именно этот случай отработал давайте напишем recuva [музыка] пикулева мы горим нам не прост нужно ошибка нам нужно ошибка вот именно вот соответствующая ожидаемый вот так вот а теперь если мы это удалим видите intel tm от type ошибку пола она ожидали предыдущую то есть теперь просто так нельзя снести кусочек кода так возможно не себя лучше куда мне себя перенести чтобы не заслонять ничего давайте снова вниз попробую вот инвалид поймать type отлично проверили один кейсик провели один из теперь надо проверить 2 3 здесь еще две проверки все это копировать 10 раз я не хочу тестик маленький это будет много копипасты давайте сделаем вот такую табличную структуру называемый css и это будут структура которые будут поставлять данных такой даты провайдер для нашего теста name это собственно имя того чтобы проверяем name и tostring будем border in давать in это ordering и будем ожидать какую-то ошибку tags name в первом случае что мы проверяем белью сзади так и я прямо копирую ожидаемая ошибка invalid user айди вот она здорово хендлер с о store теперь мы можем просто цикле прогнать наши кейси ты нам больше не нужен header на все еще нужен теперь мы говорим тест кейс вся какой-то in test кейс у тебя какая-то там ошибочка ожидалось и давайте еще вот так таран мы сейчас разводим тесты друг от друга отдельно теста можно параллельно запускать чтобы они быстрее проходили пока мы не будем идти выпустить тем не менее поместим это все просто тиран скажет каждый тест запустить пожалуйста отдельно вот то есть мы сейчас этот тестик поместили в сlassic сlassic прогнали запустили в нем тест тест должен пройти ok давайте тоже самое теперь сделаем для остальных случаях мы их под прям по порядку и проверяем кто-то будет смотреть скорее всего сразу поймет о чем наш тест bad юзера и д.б. user айди уже должен быть 1-а поймали type должен быть нет карт и не вырыты если я правильно помню да карты имеют я это все потом вылеты превращаю винты чтобы баски сохранить но приходит нам это в виде строк а там с мы можем не передавать тоже мы до них не дойдем давайте запустим тест сейчас у нас нет ошибка который ожидает юзера и де батца в кейсе bad поймали type у нас неправильная ошибка ну конечно давайте разместим правильную ошибку отличных проверили второй случай 3 это когда мы anthems и передали хорошо здесь уже карт уже правильно все но рмт ой там здорово четвертый случай мы передадим а это мтс я этом у нас будет не валидный у него эдюшечка будет ноль это у нас инвалида это моя ошибочка и последний случай только на переименовать это название довольно важно вот если такой тест упадет какой случай какой случай из него сломался нам надо быстро понять и починить это бета idem прайс были дома айди mount 0 давайте посмотрим сверху вот у нас большая секция где мы подготавливаем данные а сам запуск тестов довольно маленький меня это вполне устраивает если мы хотим конкретно кейсики посмотреть сможем их полистать посмотреть запустим тест и океане проходят теперь как давайте давайте что-нибудь сломаем опять-таки уберем какую-то проверку убедимся что у нас будет ломаться какой-то тест опять их видите бодай команде уже не проходит тест потому что кто-то испортил нам код то есть у нас есть защита этого кода мы написали такой простой тест 5 10 минут это потратили и уже получили некоторые гарантию что валидацию у нас не отключат что всякая гадость в базу к нам не полетит с user 10 там ничего не запишется сайтом 10 там ничего не запишется безо этого заказ создан не будет здорово какой слой мы протестировали он зелёненький кусочек зеленого строя маленький unit-тест написали получили гарантию что с него личными данными мы дальше не идем и у нас ничего в маске не разъедутся гарантии не самое сильное но очень важное давайте-ка скажем что мы тестики здесь написали похвалим себя поставим их зеленым и теперь я что хочу я вот очень хочу убедиться в том что все кейси проверены вроде все ломается мы глазом это хочу увидеть у меня есть для этого инструментарий у нас есть такая такой понятно как каверы тестовое покрытие вот я вмиг файлики завел некоторую команду кого он прогоняет tst кстати давайте ка он будет их прогонять каунт тоже добавим чтобы не копировалась ну и райс тоже добавим создает некоторый файлик коврах профан carried out на всех тестах проекте потом через год у кого мы запускаем его и просим вывести вычтем или браузере можем в разные места выводить сейчас хотим браузере посмотреть и удаляем этот временный файлик у нас примут создастся на уровне проекте к давайте сделаем мой товар отлично так у нас один файлик покрыт тестами на 30 процентов серые строчки это то что тестировать никак нельзя потому что ну импорт и объявления переменных мы от никак не протестируем а вот красненьким этот что то что исполняется но никем не тестировано вот у нас конструктор не тестируются перекладывание из dota уже в ордер не тестируется собственно не тестируется и сам хендлер это уже api тест будет когда мы захотим его сделать это все покроется зеленым но не сейчас это будет после но вот здесь вот видите зелененькое покрытие собственно мы проверили все эти случаи кстати сверх они такие более яркие и снизу менее яркие то почему это нам показывает интенсивность виде тихой камеры чита вот у нас много тестов пробежались по этим условиям они более яркие и здесь лавка врач на вот одна проверка была нас вполне устраивает просто нам визуально я такая подсказка иногда мы ожидаем что на все будет равномерно иоанну бац какую-то более black lacquer стоп стоп что значит что-то не так вот то есть ну две матрицы процентов покрыли потратив всего несколько минут сделали такой юнин тестик теперь давайте поговорим о том как нам протестировать собственно наш русский сик но здорово здорово валидация прошла а с бизнес-логика что делать будем вот вот с этим красненьким кругом что делать будем она все в базу запишется или нет мы же не можем базу держать постоянно поднятой чтоб тесты гонять здесь у нас возникают некоторые проблемы так к врач прошел это можно закрыть это можно закрыть давайте давайте посмотрим вот у нас наш кейс в нашем из кейси у нас есть проблема у нас там бак не который спрятан еще у нас есть проблема в него передается конфиг он создает репозиторий прямо вот здесь репозитории внутри создает pejic проверяет connect и это провал вот эта зависимость она прибита здесь гвоздями нельзя создать репозиторий не создав рабочий пул нельзя создать новый у space не создав репозитории и репозитории он всегда пойдет в базу то есть даже если мы просто создадим эту структуру с пустым ли по историям перед пустую структуру куда репозитория подсунем то есть без конструктор если все будет все равно на вызове этого метода все развалится про что у нас там базы нет будет сиквел что делать нам нужно эту зависимость с помощью композиция объектов как-то передать наверх как-то нужно вот развязать и и отсюда она не должна создаваться здесь потому что пул создается один раз в процессе инициализации приложения ну давайте скажем что этот пул будет передаваться откуда-то сверху edix здорово уже не привязан теперь создания репозитория к настоящему полу потом мы можем какие-нибудь абстракций пацанские диктор фейсы и хакан систему вынесли сюда все это дело кнопочки тоже не очень хорошо надо бы еще на верху вынести давайте так и поступим давайте скажем что can fix до передаваться не будет сюда уже готовый будет передаваться даже не пул давайте скажем что сюда готовый будет ордер репозитории передаваться пускаем где-то сверху создастся ордер репозитории warfare по так по указателю по указатель здорово теперь мы внутри ничего не создаем получаем все объекты сверху у нас не прибиты не захардкожены зависимости так уже намного лучше так здесь мы ошибочку то наверх передаем давайте не будем умирать прямо на месте не очень хороший это стиль нам будет фнтр это инициализация если здесь мы провалились пожалуйста верни ошибку наверх ей место так что то я что-то я потерял наш репозитории там где где же он является затем заново так давай как-нибудь [музыка] репозитории окреп они нет давайте где он отдавать путь проставим путин не подтянулся arcgis кейс есть поттер рэпа прыгаем репозитории or to [музыка] the new здорово теперь у нас вот эта зависимость репозитории она отдельно от нашего из кейса она передается сверху но она все еще требует настоящую базу данных нас это не устраивает мы хотим это дело как-нибудь пофиксить здесь нам нужно абстрагироваться от конкретной реализации возможно вы слышали о таком что зачем интерфейс абстракция какая то вот у нас есть репозиторию у него два метода сэйв get вот я уже набросал интерфейс собственно теперь репозиторий соответствует некоторый интерфейс ордер рэпа можно подсунуть что угодно что имеет эти два метода выполняют этот контракт вместо настоящего репозитория здорово еще близкий с об этом узнал да давайте ему тоже скажем парень тебе будет не конкретная реализация тебе будет какой-то интерфейс приходить ничего не изменилось потому что у нас просто поменялась структура на интерфейс методы те же поэтому все окей поддержка довольно мы довольны код компилируется так но у нас проблема у нас нету какого-то фейкового реализатор этого репозитории нам нам нужно что-то подложить что же нам предложить давайте посмотрим и я расскажу вообще какие у нас бывают тестовые двойники бывают фейки стопы и моде они все разные что такое фейк это упрощенная реализация какого-то функционала например мы можем написать ручками еще один репозиторий с таким же интерфейсом но у него будет не база данных а просто хеш-таблица где он будет по каким-то например айтишником покалечат хранить значение и это будет такой фейк то есть а на самом деле хэш-таблицы а мы думаем якобы базы данных но мы абстрагирован и нам все равно то есть упрощенная имплементация которым руками пишем стопы это упрощенное решение то есть мы можем написать структуру у нее тоже методы методы get есть она соответствует интерфейсу и она нам всегда отдает какой-то заранее готовый ответ то есть она дает нам заказы просто 123 все на их отдает всегда статичная цена всегда там статичной скидка айди могут на быть полезны для каких-то сценариев простых но какие-то интересные и сложные вещи мы точно не протестируем с таким подходом и последние маки мы сейчас немножечко потрогаем макет интересную же вещи мы можем создать некоторый интерфейс и говорить ему а как он должен действовать мы можем говорить если мы тебе передали какие-то аргументы вот такие пожалуйста ошибка на верни в ином случае верни нам положительный ответ то есть мы можем эмулировать что база данных отдала нам ошибку или базы данных о данном 200 успешно успешный результат выполнить свою работу а вот и с этим что-то делать можем говорить что вначале нам отдай ошибку а потом успешно или мы можем сказать что данный метод должен быть вызван только один раз или минимум один раз или максимум сколько ты раз то есть можно варьировать поведение этого интерфейса это то чего мы хотим на самом деле обычно у нас теста должны прогреть разный картер кейсы а если здесь ошибочка если дальше ошибочка а если один метод интерфейса вернул успешный ответ а потом второй ошибку мы все эти сценарий хотим проверить и в данном случае нос кажется довольно простеньком будет всего один метод будет вызываться но все равно мы посмотрим что такое мотьке и уже начнем их использовать так как нам выйти из режима трасса из режима демонстрации давайте возьмем библиотеку go мог есть несколько популярных библиотеку мог наверно самые популярные но есть еще тесте фай есть еще mockery у них есть некоторые свои плюсы и минусы но в целом работают они по точно такому же принципу вам понадобится его установить и у вас появится команда маген здесь очень много флагов сейчас нам нужны только флаги source то есть источник с из каком интерфейсе мы будем генерировать наши фальшивые интернет интерфейс и реализации для тестов и достигающим куда мы будем вот эти вот сгенерированные структуры класть давайте перейдем visual studio я уже в мексике взял себя смелость написать данную команду то есть мог ген источнику указываем наш файлик go в которым лежит интерфейс пункт назначения сделали еще папочку макс и там мог их репозитории есть несколько способов организовать вот эти вот команды для генерации кто-то складывает этом и кв а или как я кто-то может это описать прямо над интерфейсом там такая команда go генерит и так далее я предпочитаю все-таки складывать в майк файле чтобы все они были в одном месте я все хочу видеть всех и хочу контролировать так вот у нас муки генерировались репозиторию его нас папочка макс мог репозитории что это такое какая то структур очка у нее есть методы get и метод сейф также есть еще другие методы уи-уи рекордер а также через рефлексию замок будет имитировать какое-то поведение сейчас мы к этому прикоснемся так хотим протестировать из кейс до уровень бизнес-логики хотим протестировать что если база данных все нам ответила хорошо там и вот здесь вот какую то работу проделаем полезную получим нужный нам ответ так ордер тест удаляем здесь также тест get так мог мог мог мог так где же мой мог где же где же так тёрну . давайте вставим его до путь репо мог создаем новую структуру она требует у нас бог контроллера глубокую нужно постоянно какой-то рекорда создать может пока просто запомнить что хотите использовать всего моя создаем глубок new контролю и в конце теста скажем пожалуйста сразу же его отпустим так вот мы создали репозиторий фальшивый теперь нужно создать у space ура интерфейса сошлись что нам еще нужно на сколько я помню нам нужен был контекст лагер и ордер вот эти вот нам сущности нужны давайте их создадим здесь вот лагер просто проинициализируем настоящий так идем у нас там в cmd лежит же нет он лежит вот здесь правильно помню блогер да [музыка] так сделали лагер сделали настоящий лагер это кстати тоже можно всем опыт но в данном случае пускай камеру лагерь будет настоящий так теперь теперь мы хотим в репозитории нам нужно нужно подготовить структур take your space сейф и они из кейс с его легенд мы хотим тестируем гент сейчас значит на значит надо get значит надо делать ген так что там у нас значит на пока вор не нужен значит там важно идиш ники один два три четыре у нас 123 передали их так контекст log in он нам что отдает он нам дает на выход список заказов и ошибку мы хотим сказать что утверждаем что ошибки не будет и ardors у нас пока ничего с ним не делаем так вот мы создали пестик получается говорим мы не ожидаем здесь ошибки очень странно что мы не ожидаем ошибки по что мы поведение пока никакого не обозначили нашему имитатор у сейчас будет ошибка что тут у нас говорит мама говорит я я немножечко не ожидал ты создал вот говорит мог отдых репозитории и на нем вызвал метод get я не ожидал что это так поступишь пожалуйста расскажи мне что делать в таком случае но моему должны помочь вот мы создали репозитории и мы говорим репозитории expect ожидай метод get с параметрами контекст лагер я дичь никами верни нам два значения нужно вернуть давай нам вернет нам еще один а тут хоть тоже будет ошибкой сразу мы ожидаем будет ардак она вернет нам удары нам вернет один орда с где единичка time art и а поймать этот у нас уже винты я уже в базу это перекладывают другого пойман той давай тоже единичка иайдо хочу мы мы мы сейчас думаем что она должен этот баска данных должна найти вернуть можно было бы единичек у этого хорошо айдишник давай будет 2 м сто discount атаман скидочка 10 вот мы ожидаем что нам вот такой ответ вернется и вызовем и это все один раз уточняю там витязь метод я не таймс сколько угодно раз мы сейчас точно знаем что надо один раз лишь попробовать не надо второй раз так так так cuff аргумент новый ордер ордер is not as a и на болту мы я значит говорю я верну тебе слайс я не прав я не прав почему потому что в репозитории я для удобства для своего сказал что я вернул хэш-таблицу надо исправляться тут будет он говорит что внутри тебя немного соли на был я не могу эту структуру сам переложить пожалуйста все попросите ну им вначале этот рейс может немного сбивать но потом привыкаешь вот аргумент 0 туре тер то есть не устраивает go мог что вот were there не 0 аргумент какой-то какой-то левый оказался так map и у int64 у нас это юит этот айдишник будет у нас вот он 1 1 теперь теперь он должен быть доволен я вернул то что соответствует и в работе о metrics каун трупа помните я говорил вам что то суп метрик нету мы их глобальные инициализировали в пакете main нам у нас их нету вот на уровне нашего из кейса вот мы взяли инициализировали здесь сделали имеет вас у нас все метрики инициализировали а мы их не передали мы их не передали в конструктор и мы их не передали функцию нырнул в конструктор было бы как-то именно каутер положить или зарегистрировать самому мы глобально сделали то есть видите зависимость у нас есть такая за hard кожаная получается что же делать на самом деле вот раз мы такое решение я принял есть предложено за это платите говорить metrics пожалуйста и нет инициализировать метрики теперь должен в начале теста который используют метрики потому что все уже завязался на этой а вот вот у меня уже вызов идет видите то есть если бы я это как-то инициализировал здесь и себя и сделал бы в нью там и нет метрик какой-то одной метрики это было бы намного лучше но я уже вот принял такое решение не приписывайте мне теперь весь код вот потом а3 факты о тест выебал дин мы получили какой-то ответ и там нету ошибки здорово так давайте теперь усложним наш тест так вот у нас будет заказ пройдя 112 и вот у нас у них разные айтемы здесь один два два ручки здесь вот так так теперь и напомню что у нас делают метод картер он получил guitars он получил вот эти вот вот эту вот кнопочку он по ней идёт и он якобы должен просуммировать все mount и discount is айтемов сам кордов потом все это должен приложить слайс [музыка] так как мы получили ордер и мы теперь давай давай это не эксперт отрез потому крест на крест и теперь мы скажем что у нас есть экстрактор это вот та чтобы в конце как раз получим вот это уже ордер ордер они будут немножечко получается у нас обогащенными так 110 оригинала mode 1100 то есть discount это матриц мы ожидаем что некоторые суммирование должно произойти ну а здесь оригинального 100 discount of the mount экспорта так проверили что нет ошибки теперь проверим что эклз колб ardors спектр фиордов вначале то что мы ожидаем потом то что мы получили давайте запускать отлично видите вот здесь интересно вот она будет я ожидал увидеть или одно значение получил несколько другое здесь конкретно вот ожидалось вот такое суммирование а получил 0 и ожидался вот такое не сложилось видите то есть уже этот код будет защищен когда мы сейчас починим уже вот такую ошибочку нельзя допустить если мы тесты написали в чем здесь смысл что мы взяли из map и ордер прибавили к нему но его надо 5 положить в хэш-таблицу сингл ордер давайте давать вот сингл к ордер давайте нам нужен еще и вот яндекс и скажем вот асмап мы по индексу взяли что-то мы по индексу хотим положить что-то нам это поможет вот помогло вот то есть мы просто скопировали значение сейчас до этого увеличили его но теперь вы его положили обратно отлично код наш работает давайте посмотрим что у нас с кори рича так вот у нас ордер смотрим а мы протестировали успешный сценарий здорово но мы не протестировали сценарий когда что-то пошло не так хотелось бы убедиться что и он у нас работать давайте его сделаем это уже все умеем на самом деле копируем данный тест сейчас намного все проще будет потому что оно мне не нужно ожидать что нам какие-то структур ки вернуться не ними вот нам просто ошибка вернется опять вот мы передали tez gel error опять мы передали вот это все получая какую ошибку какую ошибку по получим только мы оборачиваем некоторую некоторую ошибочку так хорошо так давайте репо р а [музыка] теперь дал якобы нам база данных что-то такое ответим репозиторий якобы что-то такое ответят берем вот вот эту ошибку получив и мы это оборачиваем поэтому мы теперь ожидаем что будет будет вот так и так вот у нас ты так вот все правильно значит мы полученную ошибку от репозитория кладём вот сюда соответственно вот эту строчечку тут сами избил деле давайте запустим expect и дорог мы ожидаем что будет ошибка и ожидаем что такое ожидаем что данная ошибка соответствует [музыка] обученный вот так вот реклама error роковая давайте и ql террор и рекой а мы ожидаем что ardors там будет мало там ничего не должна причинам так вы написали кран тест так ррл define the [музыка] где у нас ту я создавал пакеты rfc хотел о тест прошел здорово то есть мы говорим верни нам пожалуйста ошибку в этом случае вы за все один раз проверяем что ошибка вот соответствует нашей проверяем что больше нам ничего не вернулась такс-такс-такс давайте запись запустим снова грыж хоп что-то не так пошло duplicate метрик get ардон почему у нас duplicate метрик может быть понимаю-понимаю мы запустили вот эти пакетные тесты мы запустили их сразу же вот-вот по одному они проходят а каждый из них регистрирует все метрики вот вместе запускаем ошибка давайте попрекать метрикой разберемся так в чем здесь дело что мы два раза эту функцию вызвали в одном пакете метрики попробовали зарегистрироваться дважды вот и у нас тут видите паника если не только уже зарегистрировано ну вот глобальный пакет объявили давайте теперь metrics ом резистор в принципе мы имеем право так поступить мы говорим если мы регистрируем метрики много раз глобально то надо не падать с паникой надо отменять предыдущую регистрацию регистрировать заново так все теперь проблему здесь устранили хорошо видите глобальный пакетном усложняет тестирование сразу же окей к в 70 процентов то москве это ошибка бывает что то видел что-то не вижу возможно у нас ошибка в том что у нас как-то в разном положении заказы давайте попробуем icover сделать мне вроде все в порядке вроде ошибки ушли так смотрим вот у нас проверено оба сценария теперь у нас и ошибка проверенная и успешность сценарий проверено отлично то есть мы можем гарантировать что у space на get работает давайте быстренько практически копипастой сделаем на сейф делаем сейф уже все это умеем делаем says i take you space сын так так так в и передаем там ордер border какой-то нам на самом деле сейчас совершенно неважно вот опять таки дпс down metrics им он только ошибку возвращает так [музыка] так хочет хочет вот так я понимание конец [музыка] не массив а одну хочет так отлично проверяем что у нас ошибочка вернется то есть если у нас репозиторий вернул ошибку то собственно и мы здесь тоже вот вернем эту же ошибку крайне примитивный метод потому что мы больше ты ничего не делаем но все равно сделанный р да даже да даже не будет просто проверим что есть ошибка так весь голос ну конечно вот а я уже забыл сделать я же вызвал get a надо вызвать саиф он не ожидал такой подлости от меня так borland добро а ну конечно теперь при тёрни у нас только только один аргумент я извините ожидал что у вас метод 1 черный 1 аргумент возвращает вы туда два запихали вот мы уже проверили тест chevron и теперь просто проверим тест сэйю успешный делаем здесь сделаем мог ошибки у нас не будет ошибки не будет мы говорим когда вы все будет репозиторий нам вернет нам вместо ошибки можно сказать вас новгород запустим здорово посмотрим говоришь так сто процентов мы вообще протестировали нашим юнит тестом полностью наш русский да вот у нас получается закрыта вот здесь вот красненькие юнит тестами закрыт аккурат можно быть надежным что может быть уверенным что кто-нибудь придет оригиналом а он случайно вот так вот поменяет написал отдельно не пройдет тест не пройдет файл файл файл видите ругается ругается а если поправим работает все работает даже хочется еще еще более быть уверенными что у нас теста не моргает этот акт упала а разочек давайте моих тест [музыка] сделаем тест [музыка] очкам 100 сделаем облачке что у вас такое что то у нас такое и у нас видите что-то не эквол что-то не сходится эти запустил тестик много раз запустил сто раз а я ожидал что сто раз будет он успешно пройден не будет никакой ошибки а у нас что-то моргнула вот то есть от называется флаг ищем тесты которые то работает то нет так один у нас в чем [музыка] длина 23 на 2 понятно кажется вот у нас мы получаем данных из репозитория в хеш-таблица в хэш-таблице даны в случайном значение да я указал два ордера он их взял в одном порядки вернул я же должна 1 проектируя там дела в другом порядке вернул да я вот такого не ожидал вот у нас тут ордер а иди . а второй ордер где вот другая вот они у нас и перепутаны то есть у нас в хэш-таблице не нормирован порядок то надо как-то исправить да так справить мы это можем на самом деле мы не хотим как-то кот переписывать что можно отсортировать в коде но давайте просто попробуем посмотреть какие нас проверки есть в recuva это вот есть нас рекорд по моему есть элемент сменить такая штука что мы должны дать лист и в любом порядке не должны сходятся должны сходиться вот 1 3 2 3 1 3 2 вот expected or does то есть они не одинаковые просто у них элемента совпадают давайте-ка этот тест прогоним то есть прогнали хорошо давайте опять теперь мэйк тест 100 запускаем наши тесты 100 распуская не проходит если что они уже сто раз прошли вот так вот быстро вот до горизонта прям с интеграционными тест так-то быстро не будет но с юнитами можете написать и выберем запустить его тысячу раз если он прошел сотку раз значит с не моргает всегда работает а если он флаг аид мигает один прошел другой нет значит что-то не так или с кодом что-то не так или с тестами что-то не так в принципе могли бы и знаете просто отсортировать полученные слайс тоже но уже как то ли нет описать напишем следующих итерациях если они будут итак давайте резюмируем что мы сегодня разобрали посмотрели посмотрели пирамиду тестированию знали какие вот есть тесты потрогали юнит-тесты при написании тестов стали думать о том а что мы проверяем проверяем диски ok проверяем например валидацию ноги твои окей честно себе сказали api роутинг у нас не проверен мы не знаем ни у нас гарантии что вот кто-то нам не зайдет в хендлер не поменяет где у нас тут ручки-то где у нас тут ручки [музыка] не поменяет вот эти вот наши пути и у нас все не сломается такой гарантию у нас нету мы ее не делали этапе тест это дальше уже говорим что валидации что гадость в базу не попадет окей написали тест и без зависимости и написали немножко тестов с зависимостями но вообще молодцы то есть уже какую-то как какие-то гарантии наш код даёт уже не так просто его сломать если то вначале просто все функциях удалять извините так так не работает все сломается посмотрели какие бывают тестовые двойники фейки стаба и моки собственно на это наверно код мы писать заканчиваем так как меня побольше сделать вот так и из себя хотел перетащить пишите было ли вам это видео полезным может я что-то упустил поправьте в комментариях мы разобрали только вот такой базовый функционал что мы вызвали что-то вернули мы не разобрали многоступенчатый функционал там очень много интересного пишите если хотите об этом узнать мы ну не написали мы интеграционных тестов потому что и так уже видео долго велась если интересно мы можем пойти туда написать интеграционный тест весь наша api протестировать можем написать какие-то асинхронные еще вещи например записали в базу и в кафку демон берет из базы и в кафку сообщения пуляет надо еще там кафку мокнуть как это тоже все протестировать он уже обычно не просто api сервера какие-то еще асинхронные задачи крутится-вертится что-то делается мы точно также можем подделок брокер сообщения например кафку и поработать с ней пишете было ли вам это интересно будет для вам полезно копнуть глубже в общем и любые отзывы будут полезны и хочу добавить что данный маленькие сервис я выложу на git хоп и или в таком виде или почти в таком возможно сделаю 2 папочки что было вначале что стало после первой итерации и выдают сможете при желании вас качаться и не только смотреть видео но и собственно походить по файликом вложить это все в голове возможно самостоятельно написать какие-нибудь тестики в общем поиграться с тем с чем я работал ну теперь пожалуй действительно все всем пока если после просмотра видео у вас остались какие то вопросы не все понятно или steady для грядущих видео что то в чем вы хотели бы разобраться в программировании напишите об этом в комментариях кстати напишите насколько интересна вам было бы увидеть продолжение где мы пишем уже интеграционные тесты и рассуждаем об их гарантиях а если вы хотите прокачиваться еще быстрее то можете перейти по ссылочке в описании наш telegram.bot найти себе метров навыках и ускорить свое развитие