Валерий | AQA Engineer | Автотестирование на Python | REST, gRPC, GraphQL
رفتن به کانال در Telegram
Сделаю из тебя крутого AQA инженера на Python. • Преподаю лучшие тренинги по автоматизации тестирования API • Senior Python developer | AQA lead, 7 лет в IT
نمایش بیشتر1 511
مشترکین
-124 ساعت
+57 روز
+830 روز
آرشیو پست ها
Привет, друзья!
Вчера на вебинаре прошли весь путь – от базовых вещей до архитектуры полноценного фреймворка. Написали достаточно кода, чтобы понять, как выглядит по-настоящему сильное решение.
Я не люблю воду на вебинарах, поэтому сделал его максимально прикладным и техническим – только практика, только хардкор.
Что выяснили:
- На написание одного хорошего автотеста (с учетом опыта) уходит ~1,5 часа
- Но это без учета сопровождения – а там могут быть бесконечные правки и доработки
- С правильными инструментами тот же тест пишется за 5 минут (да, в 18 раз быстрее!)
90 минут против 5 – и это без учета времени на настройку линтеров, CI/CD и прочей инфраструктуры.
Это не просто экономия времени – это возможность:
✅ Развиваться вместо бесконечного фикса багов
✅ Делать сложные задачи легко
✅ Стать настоящим Senior’ом, а не просто "поставить галочку" в резюме
Пока другие крутят "опыт" и продают вымышленные успехи, вы сможете:
🔹 Писать чисто, быстро и профессионально
🔹 Работать с реальной технической базой (а не поверхностными знаниями)
🔹 Сократить не только свои трудозатраты, но и бюджет компании
Мои тренинги я считаю лучшими на рынке – и это не просто слова. Многие студенты после них растут в 2-3 раза быстрее коллег.
Хочешь так же? Присоединяйся – научу!
Старт уже в понедельник 7 апреля!
А если пропустил вебинар – обязательно посмотри запись, пока она доступна. Это сильный рывок даже для тех, кто уже в теме.
P.S. Разница в 18 раз – это не магия. Это знание того, как делать правильно. Если хочешь таких же результатов – пиши, расскажу подробнее. 💪
Описание всех тренингов можно найти тут
Как развернуть автоматизацию тестирования API за неделю?
Уже завтра стартует вебинар "ОТ ТЕСТОВ К ИНСТРУМЕНТАМ"! 🚀
📅 Когда: 03.04.2025 20:00 - 22:00
📍 Куда вступать: группа
Плюс будет маленький бонус тем, кто досидит до конца! 👀
Поэтому, если ты еще не вступил в группу, советую это сделать.
А пока расскажу, как моя жена развернула автоматизацию на проекте за неделю.
У нас семья айтишников, и было бы глупо полагать, что она не имеет свободного доступа к моим курсам.
Я не люблю помогать)))
Это высказывание не совсем вяжется с тем, что происходит на самом деле. Моя телега обычно трещит от вопросов, и я всегда отвечаю. Просто я не люблю быть чатом GPT и просто говорить, как тут сделать. Я всегда вместо "рыбы" пытаюсь дать "удочку".
Почему?
Да потому, что я очень ленив. Мне проще один раз научить человека, чем он будет приходить миллион раз с типовыми вопросами.
Примерно так же было, когда с таким же запросом ко мне пришла моя жена. Как мне развернуть автоматизацию у себя на проекте?
Я сказал: "Вот курс — смотри." Наверное, можно было сесть, все показать и рассказать, но зачем, если я уже снял видео? ))
Для нее это был жуткий марафон. С утра до ночи она сидела и все пробовала. И вот спустя неделю у нее уже работает pipeline, прикручен Allure, логи, степы, уведомления о прохождении сыпятся в телегу, и при падении могут тэгать нужных людей.
Как вы думаете, это быстро, учитывая, что человек до этого ни разу не писал код? 🤔
ЭТО ПИЗДЕЦ КАК БЫСТРО! 💥
А схема получилась проста: большую часть времени занимает написание клиентов, поэтому она их просто генерирует, а дальше заполнение сценария не сложнее, чем выполнять то же самое в Swagger или Postman.
Получился такой флоу:
генерирует клиент -> делает фикстуру -> пишет тест.
К концу второй недели она уже покрыла 90% сервиса смоками — 88 автотестов, и это не статус-код 200, а реальные бизнесовые проверки с хождением по разным сервисам.
Есть ли тут подвох?
Да, есть.
Эти инструменты я даю только на ступени professional. Можно будет остановиться только на их использовании, и это уже ооооочень сильно сократит время. Но главная фишка этого обучения не в этом, а в том, что я буду давать именно удочку. Мы сами научимся писать генераторы кода, чтобы вы могли писать свой кастом под свой проект или дорабатывать инструмент при переходе на другой проект.
Вчера я тестировал инструмент, который будет итогом обучения professional, и это очень круто! 😍
Я думаю, вам понравится тоже.
Об этом и многом другом мы поговорим уже завтра.
А пока ступай в группу вебинара, если этого еще не сделал! 😊удалил(-а) Вас из канала
Принцип YAGNI (You Ain’t Gonna Need It) — «Тебе это не понадобится»
Часто на картинках с DRY и KISS мелькает еще один важный принцип — YAGNI. Он гласит: не добавляй функциональность, которая может понадобиться в будущем, но не нужна прямо сейчас.
Основные идеи YAGNI:
1️⃣ Не реализуй то, что не требуется сейчас — если нет конкретного ТЗ, не пиши код «на всякий случай».
2️⃣ Избегай ненужной сложности — лишний код усложняет поддержку и тестирование.
3️⃣ Оптимизируй только при необходимости — преждевременная оптимизация может навредить.
4️⃣ Экономи время и ресурсы — меньше лишнего кода = чище и понятнее архитектура.
Примеры нарушения YAGNI:
- Абстрактная архитектура «на будущее», которая никогда не пригодится.
- Параметры в функции, которые пока не используются.
- Сложная система логирования для одноразового скрипта.
Хороший принцип… но я его нарушаю в автотестах😅
Вот как и почему:
🔹 Генерация клиентов
Если писать клиенты вручную, логично описать только нужный контроллер для нужного API сервиса. Но я давно использую сгенерированные клиенты — и если генерировать, то все сразу.
🔹 Версии API (V1, V2, OLD и т. д.)
Контроллеры в разных версиях API могут называться одинаково, и появляются фикстуры вроде old_controller_api, v2_controller_api и т. п. Проще сразу сделать фасад, который объединит API (контроллеры) одного сервиса, где через точку можно доставать нужный, вместо того чтобы путаться в версиях контроллеров.
🔹 Обёртки над методами
Контракты меняются, и если не подготовиться, придётся переписывать все тесты, а не один метод-абстракцию. Поэтому я довольно часто добавляю еще один класс, в виде наследника от API клиента, в котором упрощаю интерфейс тестируемого метода.
Да, это усложняет проект, но зато даёт архитектуру, которую легко поддерживать годами.
А если все это генерировать это вовсе сводит трудозатраты к минимуму, задавая чёткие рамки проекта.
Вывод: YAGNI — хорошее правило, но иногда его можно нарушать осознанно. Главное — понимать, зачем.
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
В посте выше в комментариях верное отметили, что говоря про DRY, нужно не забывать про KISS.
Принцип KISS (Keep It Simple, Stupid) — один из ключевых в разработке.
Его суть проста: чем проще ваш код, тем легче его поддерживать, масштабировать и понимать (вам и другим разработчикам).
Почему KISS важен?
1️⃣ Меньше багов — сложный код = больше ошибок.
2️⃣ Лучше читаемость — коллеги (и будущий вы) скажут спасибо.
3️⃣ Быстрее разработка — не нужно изобретать велосипед.
Я точно знаю, что есть проекты написанные мной еще 4 года назад, которые работают и поддерживаются по сей день. Все потому, что были написаны очень просто и понятно, как молоток.
Как применять KISS?
✔️ Дробите задачи — одна функция = одна ответственность.
✔️ Избегайте "умного" кода — если решение требует сложных объяснений, возможно, есть вариант проще.
✔️ Рефакторите — если код стал запутанным, упрощайте без жалости.
✔️ Используйте проверенные паттерны — но не усложняйте там, где можно без них.
"Совершенство достигнуто не тогда, когда нечего добавить, а когда нечего убрать."Ваш код должен решать задачу, а не демонстрировать интеллект. Старайтесь писать проще! ——————————- 📱 TG-сообщество 📱 Обучение 📱 Отзывы
✨ Принцип DRY (Don't Repeat Yourself)
Это один из основных принципов программирования, который утверждает, что "не следует повторять себя". Он призывает избегать дублирования кода и данных, что помогает упростить проектирование, повысить качество кода и снизить вероятность ошибок.
Основные идеи DRY:
1️⃣ Устранение дублирования
Если код или логика повторяются — выноси их в отдельный модуль, функцию или класс. Так любые изменения потребуют правки только в одном месте.
2️⃣ Упрощение поддержки
Меньше дублирования → проще тестировать и обновлять код. Никаких "а не забыл ли я поправить это в другом файле?"
3️⃣ Улучшение читаемости
Чистый и структурированный код легче понимать и поддерживать.
💡 Как применять DRY?
Используй функции, классы, библиотеки и паттерны проектирования, чтобы избежать повторений.
🎯 Как мы применяем DRY с учениками?
✔️ Логгирующий клиент — один класс для всех логов, а не копипаста в каждом тесте 📋.
✔️ Хелперы и врапперы — позволяет зашить логику проверок, разметки и другие полезные действия в одном месте, тем самым появляется как бы "авторазметка" и "автопроверки", так как использование методов из классов уже содержит все необходимое.
✔️ Декораторы — позволяет добавлять новый функционал к уже существующим методам, всего одной строчкой.
✔️ Фасады — позволяют определить одну входную точку в нужный клиент, вместо написания большого количества очень похожих фикстур.
✔️ Используем наследование и другие возможности языка, для уменьшения дублирования кода.
Использование этих подходов позволяет здорово улучшить поддерживаемость, стабильность и чистоту кода нашего фреймворка.
——————————-
📱 TG-сообщество
📱 Обучение
📱 Отзывы
🚀 От тестов к инструментам: как сеньеры создают фреймворки за пару кликов
Привет, коллега! 👋
Если ты хоть раз задумывался, почему одни пишут тесты часами, а другие — за пару минут, то этот вебинар для тебя!
Я расскажу:
✅ Как джуны, мидлы и сеньеры подходят к автоматизации — и почему это выглядит как "слоумо" vs "вау, как он это сделал?".
✅ Как сеньеры создают целые фреймворки в пару кликов, пока остальные пишут сотни строк кода?
✅ Как перейти от написания тестов к созданию инструментов, которые делают всю работу за тебя?
💡 Секретный ингредиент: Я покажу, как с помощью одного инструмента можно генерировать целые фреймворки автотестирования, которые экономят часы, дни и даже недели работы.
Минимум воды максимум пользы, мы будем заниматься лайфкодингом.
📅 Дата и время вебинара: 03.04.2025, 20-00 по МСК
📍 Где: В этой группе (обязательно подпишись, чтобы не пропустить!)
👉 Почему стоит присоединиться?
- Новичок? Узнаешь подходы к автоматизации и построению фреймворка.
- Имеешь опыт? Узнаешь, как выйти на новый уровень в автоматизации.
- Поймешь, как писать не просто тесты, а инструменты, которые делают тебя незаменимым.
- Получишь эксклюзивный анонс моего нового курса PROFESSIONAL, где я научу тебя не только писать тесты, но и создавать инструменты автоматизации.
🔥 Вау-эффект гарантирован!
Не упусти шанс узнать, как сделать свою работу проще, быстрее и круче.
👇 Что делать сейчас?
1. Подпишись на эту группу . И этот канал.
2. Расскажи друзьям — пусть тоже прокачают свои навыки.
3. Жди анонса вебинара и готовь вопросы!
Ссылка на группу: Webinar: От тестов к инструментам
Ну и немного обо мне)
Сейчас: старший разработчик - Python платформы OzonTech
В прошлом: Ведущий инженер по автоматизации тестирования OzonTech
Ну, и просто хороший человек)
До встречи на вебинаре! 🚀
Стандартная метафора «переменные – это ящики» ведет к непониманию ссылочных переменных в объектно-ориентированных языках.
Переменные в Python похожи на ссылочные переменные, поэтому лучше представлять их как этикетки, приклеенные к объектам.
Следующий пример поможет понять, почему.
>>> a = [1, 2, 3]
>>> b = a
>>> a.append(4)
>>> b
>>> [1, 2, 3, 4]
1. Создать список [1, 2, 3] и связать с ним переменную a
2. Связать переменную b с тем же значением, на которое ссылается a.
3. Изменить список, на который ссылается a, добавив в конец еще один элемент.
4. Можно наблюдать, как это отразилось на переменной b.
5. Если считать b ящиком, в котором хранилась копия списка [1, 2, 3] из ящика a, то такое поведение бессмысленно.
Таким образом, предложение b = a не копирует содержимое ящика a в ящик b, а наклеивает метку b на объект, уже имеющий метку a.
Для правильного понимания присваивания в Python всегда сначала читайте правую часть, ту, где объект создается или извлекается. Уже после этого переменная в левой части связывается с объектом – как приклеенная к нему этикетка. А о ящиках забудьте.
Поскольку переменные – это просто этикетки, ничто не мешает наклеить на объект несколько этикеток. В этом случае образуются псевдонимы.
Тем самым оператор is проверяет, что разные этикетки наклеены на один и тот же ящик.
А оператор == проверяет, что разные ящики имеют одинаковое содержимое.
——————————-
📱 TG-сообщество
📱 Обучение
📱 ОтзывыЧем отличается оператор "is" от оператора "==" ?
Ответ на задачу выше. 🔍
Проблема в том, что все экземпляры
Bus, конструктору которых не был явно передан список пассажиров, разделяют один и тот же список по умолчанию.
Это тонкая ошибка. Из примера видно, что когда объект Bus инициализируется списком пассажиров, он работает правильно. ✅
Странности начинаются, когда Bus вначале пуст, потому что в этом случае self.passengers оказывается псевдонимом значения по умолчанию для параметра passengers.
Беда в том, что любое значение по умолчанию вычисляется в момент определения функции, т. е. обычно на этапе загрузки модуля, после чего значения по умолчанию становятся атрибутами объекта-функции.
Так что если значение по умолчанию – изменяемый объект и вы его изменили, то изменение отразится и на всех последующих вызовах функции. ⚠️
Если после выполнения кода из примера проинспектировать объект Bus.__init__, то мы обнаружим имена в его атрибуте __defaults__:
dir(Bus.__init__)
# ['__annotations__', '__call__', ..., '__defaults__', ...]
Bus.__init__.__defaults__
# (['Vasiliy', 'Julia'],)
Наконец, можно убедиться, что bus2.passengers – псевдоним первого элемента атрибута:
Bus.__init__.__defaults__[0] is bus2.passengers # True
Описанная проблема и есть причина того, почему для параметров, принимающих изменяемые значения, часто по умолчанию задается значение None. ❗️
Например:
class Bus:
def __init__(self, passengers=None):
if passengers is None:
# Создаем новый пустой список
self.passengers = []
else:
# Связываем копию
self.passengers = list(passengers)
В примере init проверяет, верно ли, что аргумент passengers совпадает с None, и, если это так, присваивает атрибуту self.passengers вновь созданный пустой список. Если passengers не совпадает с None, то правильное решение заключается в том, чтобы связать копию этого атрибута с self.passengers.
Но при написании функции, принимающей изменяемый параметр, нужно тщательно обдумать, ожидает ли вызывающая сторона, что переданный аргумент может быть изменен. 🤔
——————————-
📱 TG-сообщество
📱 Обучение
📱 ОтзывыПривет давайте еще одну задачку)
Какой правильный ответ из скрина выше?
Что выведет интерпретатор, выбери правильный ответ?
def func(x, y=[]):
y.append(y)
return y print(func(1)) print(func(2)) Что выведет код?
Ребят спасибо большое, что забустили канал, даже не ожидал такой поддержки, это позволило чуть причесать канал, еще два голоса и даже можно будет устанавливать свои собственные обои. Но не буду уж наглеть вы и так накинули очень много, еще раз спасибо большое.
Ну а пока давайте поговорим, почему в срезы и диапазоны не включается последний элемент?
Принятое в Python соглашение не включать последний элемент в срезы(slice) и диапазоны(range) соответствует индексации с нуля, принятой в Python, C и многих других языках.
Приведем несколько полезных следствий из этого соглашения.
- В математике и теории множеств удобно работать с индексами, начинающимися с нуля, так как это упрощает ссылки на позиции в последовательности.
- Легко понять, какова длина среза или диапазона, если задана только конечная позиция: и range(3), и my_list[:3] содержат три элемента.
- Легко вычислить длину среза или диапазона, если заданы начальная и конечная позиции, достаточно вычислить их разность stop - start.
- Легко разбить последовательность на две непересекающиеся части по любому индексу x: нужно просто взять my_list[:x] и my_list[x:].
l = [10, 20, 30, 40, 50, 60]
l[:2] # [10, 20]
l[2:] # [30, 40, 50, 60]
Эти четыре пункта помогают лучше понять, почему в Python и многих других языках удобнее не включать последний элемент в срезы и диапазоны. Это соглашение делает работу с последовательностями более интуитивной и позволяет избежать множества потенциальных ошибок.
TG-сообщество | Обучение | Отзывыhttps://t.me/boost/AQA_Engineer
Ребят проголосуйте за канал кому не впадлу)
Структуры данных - Множества
В прошлых постах мы говорили о последовательностях , кортежах и очередях, их видах, словарях (dict) и их вариациях.
Множества — это сравнительно недавнее добавление к Python, которое использует не так уж много разработчиков. Тип set и его неизменяемый вариант frozenset впервые появились в модуле в Python 2.3, а в Python 2.6 стали встроенными типами.
🔹 Что такое множество?
Это набор уникальных объектов. Один из основных способов применения множеств — устранение дубликатов:
l = ['spam', 'spam', 'eggs', 'spam', 'bacon', 'eggs']
set(l) # {'eggs', 'spam', 'bacon'}
Обратите внимание, что элементы множества должны быть хешируемыми. Сам тип set не является хешируемым, поэтому множества не могут быть вложенными. Однако frozenset хешируемый, и его объекты могут быть элементами set.
🔹 Операции с множествами
Типы множеств предоставляют множество операций, включая инфиксные операции:
- a | b — объединение
- a & b — пересечение
- a - b — разность
Умелое использование этих операций позволяет существенно уменьшить как объем кода, так и время его выполнения, улучшая читаемость и понятность.
💡 Пример:
У нас есть большой набор почтовых адресов (haystack) и меньший набор адресов (needles). Нам нужно подсчитать, сколько раз элементы needles встречаются в haystack. С помощью операции пересечения это делается одной строкой:
found = len(needles & haystack)
А без оператора пересечения пришлось бы написать так:
found = 0
for n in needles:
if n in haystack:
found += 1
🔹 Некоторые особенности множеств:
Типы set и frozenset реализованы с помощью хеш-таблиц. Отсюда вытекает ряд следствий.
- Элементы множества должны быть хешируемыми объектами.
- Проверка на членство производится очень эффективно. Множество может содержать миллионы элементов, но для нахождения элемента нужно только вычислить его хеш-код и получить по нему смещение относительно начала хеш-таблицы; возможно, еще придется выполнить несколько попыток, чтобы добраться до нужного элемента или убедиться, что его не существует.
- Множествам присущи большие накладные расходы на хранение в памяти по сравнению с низкоуровневым массивом указателей на элементы, что было бы компактнее, но резко замедлило бы поиск, если число элементов в множестве сколько-нибудь велико.
- Порядок элементов зависит от порядка вставки, но опираться на эту зависимость не рекомендуется, т. к. это ненадежно. Если два элемента различны, но имеют одинаковый хеш-код, то их взаимное расположение зависит от того, какой элемент был добавлен первым.
- Добавление элементов в множество может изменить порядок уже присутствующих в нем элементов. Это связано с тем, что эффективность алгоритма падает, когда хеш-таблица заполнена на две трети или более, поэтому Python приходится увеличивать размер таблицы по мере ее роста, что влечет за собой перемещение в памяти. Когда такое происходит, элементы вставляются заново, и их относительный порядок может измениться.
TG-сообщество | Обучение | ОтзывыДорогие девушки!
С Международным женским днем вас! В этот прекрасный день хочется пожелать вам, чтобы ваша жизнь была такой же гладкой, как безошибочный сценарий тестирования, а задачи были решаемыми, как баги под капотом.
Пусть ваша отладка будет не только в коде, но и в жизни! Пусть все ваши изысканные тест-кейсы завершаются без критических ошибок, а цель всегда будет достигнута — с первого прогона!
Пусть каждое утро начинается с яркой идеи и чашечки бодрящего кофе, а каждый ваш день будет наполнен теплом и радостью, как идеальное пользовательское время!
Желаю вам креативного подхода к решению задач и здоровья, чтобы справляться с любыми трудностями! Пусть вашей жизни будет столько же сладостей, сколько багов в коде, а улыбок — больше, чем нереализованных требований!
С восьмым марта! Вы — лучшие! 💐
اکنون در دسترس! پژوهش تلگرام ۲۰۲۵ — مهمترین بینشهای سال 
