Урок для начинающих по PyTest #8 | Детальный разбор pydantic и способы работы с ним в автотестах

Поділитися
Вставка
  • Опубліковано 2 січ 2025

КОМЕНТАРІ • 41

  • @ThevideOoLoadeR
    @ThevideOoLoadeR Рік тому +2

    Ну наконец - нормальный пример с вложенными объектами/массивами. Спасибо! А то все пихнут 1 классик и больше не показывают ничего

  • @duke007x3
    @duke007x3 2 роки тому +6

    спасибо, за уроки, не забрасывай канал, материал топ)
    там где то были обещания это все дело в контейнере заранить и многое другое)
    еще бы интересно пайтест в связке с БД увидеть
    енивей дякую)

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому +1

      Спасибо большое :) Сделаем отдельное видео о работе с базой используя sqlalchemy.

  • @1153rus
    @1153rus 9 місяців тому +1

    потрясающий разбор!
    единтвенное, добавил бы что name: str маловато, т.к. для платежных систем часто важно что имя именно двух или трех-словное иначе запрос не пройдет

  • @alexsanchoss
    @alexsanchoss 2 роки тому +3

    Спасибо большое за видосы) Очень классно рассказываешь)

  • @hardbox0532
    @hardbox0532 Рік тому

    все очень круто! спасибо тебе

  • @iaroslavbulimov2002
    @iaroslavbulimov2002 Рік тому

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

  • @tumoyan
    @tumoyan Рік тому

    братан контент огонь!

  • @RiksaR
    @RiksaR 2 роки тому +1

    Спасибо большое за инфу, очень полезно. Если прочитаешь, подскажи, пожалуйста, как можно решить такую проблему. Я отправляю GET-запрос с параметрами, и в зависимости от того, какие параметры отправляю, зависит ответ и длина json. Т.е., к примеру, мне нужно получить данные, допустим, название модели инструментов, которые продаются в магазине и выпущенных в 2022 году. Я отправляю запрос с параметром 'year'='2022', и мне приходит ответ вот в таком формате: {'mod1': 'пила', 'mod2': 'молоток'} и т.д. Ответ приходит всегда по одной схеме, т.е. 'какое-то поле': str, но кол-во моделей может меняться, соответственно, и длина джейсона и название полей разное, т.е. mod1, mod2, mod3, как можно в таком случае описать pydantic-схему?

  • @alexandrettio
    @alexandrettio 2 роки тому

    Здорово! Спасибо.
    Правда кажется експирейшн не совсем корректно делать FutureDate с точки зрения бытового взгляда, потому что мы можем не успеть обновиться пока компьютер не поэкспайрится

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Спасибо)))
      Я по-этому и указал 2040й год на всякий случай :D Но даже если у нас и будет идти что-то не по плану, всегда на помощь прийдут кастомные валидации для моделей)

  • @ИльяЯкимов-г2ы
    @ИльяЯкимов-г2ы 2 роки тому

    билдер на основе модели pydentic можно сделать ?

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Из коробки такое не предоставляется.
      Небольшое вступление по-поводу самой библиотеки:
      Сама по-себе библиотека изначально предназначалась для парсинга данных из объектов типа sqlalchemy, dict и т.д. Спустя время, все поняли, что это крутая штука не только для парсинга, а и для валидации данных и активно начали её форсить в связке с фреймворком fastapi, накрутили кучу фич и т.д. В этом же курсе, она исключительно для валидации данных.
      Теперь по-поводу вопроса:
      Я думал на этот счёт, что было бы весьма удобно один раз написать модель и использовать её ещё и как генератор, но пришёл к выводу, что это будут только лишние проблемы.
      1. Зачем писать ещё один уровень абстракции по-верх базового класса, расширять его куда-то в сторону, не используя основной функционал. (Проще написать обычный билдер с нуля)
      2. Управление полями которые ENUM. К примеру, мы генерируем новый тестовый объект, какое из значений присвоить для этого поля? Если дефолтное выбрать, то нужно будет в обязательном порядке менять его на другое в дальнейшем.
      Итог: Лучше создать простенький билдер используя faker, чем всю эту штуку переписывать и делать из неё прям монстра.

  • @igorsemenkov98
    @igorsemenkov98 2 роки тому

    Спасибо за уроки, но я что-то не понимаю сути происходящего. У нас приходят какие-то данные с сервера/приложения в виде json и мы для проверки генерируем свои данные?

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Привет))
      Мы получаем данные с сервера и с помощью pydantic валидируем их. То-есть пытаемся сериализировать с помощью pydantic, что намного удобнее, чем использовать довольно популярную библиотеку для валидации данных jsonschema.

  • @evzheniq9582
    @evzheniq9582 2 роки тому

    А де опублікований код?)

  • @AnacondychSW
    @AnacondychSW 2 роки тому

    А как работать если некоторые поля меняются под локализацией? Например если поле "Name" имеет английский и корейский варианты?

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Добрый вечер, можете пожалуйста скинуть пример JSON, подумаем на проблемой вместе))

    • @AnacondychSW
      @AnacondychSW 2 роки тому

      @@SolveMeChannel, ух оперативность)
      использую Pydantic в связке с SQLAlchemy для тестирования API
      Пользователь запрашивает данные пользователя и в зависимости от языка интерфейса . поля 'name' и 'department' соответственно подтягиваются с БД в нужной локализации.
      Я парсю JSON ответа ( User.parse_obj(response_json) ) и также парсю даннные со стороны Базы данных ( User.from_orm(UserDB) ) и уже на уровне Pydantic класса сравниваю
      response_json= {
      "name": "User",
      "userId": "Test userId",
      "department": "Test Dept"
      }
      модель Pydantic
      class User(BaseModel):
      user_id: str = Field(alias='userId')
      name: str
      department: str
      class Config:
      orm_mode = True
      allow_population_by_field_name = True
      в Базе данных модель юзера такая
      class UserDB(Base):
      __tablename__ = 'user'
      id = Column(Integer, primary_key=True)
      user_id = Column(String)
      user_nm_kr = Column(String)
      user_nm_en = Column(String)
      dept_nm_kr = Column(String)
      dept_nm_en = Column(String)
      UPD: пока писал, понял что скорее всего логика должна быть на стороне бека в подготовке объекта от Базы данных

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому +2

      Есть один вопросик, а именно как работает эта штука? У меня лично 2 догадки :)
      Вариант 1
      Если нет обычного имени - возвращает kr
      Вариант 2
      При запросе на сервер передают хедер accept-language с языком, если такой язык есть, в таком и возвращается имя и другие параметры (Судя по респонсу, скорей всего так и есть, так как первый вариант менее популярный). Если же языка нет или хедер не передали, то возвращают все доступные локализации и параметры к ним в отдельном обьекте.
      ===========================
      Для первого варианта:
      from sqlalchemy import func
      def get_user_data(lang="en"):
      data = session.query(
      tables.UserDB.user_id,
      func.coalesce(tables.UserDB.user_nm_en, tables.UserDB.user_nm_kr),
      func.coalesce(tables.UserDB.dept_nm_en, tables.UserDB.dept_nm_kr)
      ).first()
      return data
      Для второго варианта есть такой ход конём:
      Если ты знаешь какой язык сейчас нужно селектить из базы, то можно вот так поступить:
      def get_user_data(lang="en"):
      LANG_MAPPER = {
      "en": (tables.UserDB.user_id, tables.UserDB.user_nm_en, tables.UserDB.dept_nm_en)
      "kr": (tables.UserDB.user_id, tables.UserDB.user_nm_kr, tables.UserDB.dept_nm_kr)
      }
      data = session.query(LANG_MAPPER.get(lang)).first()
      return data
      PS: Надеюсь я правильно понял суть проблемы :)

  • @fctrade
    @fctrade 2 роки тому

    Спасибо большое за уроки.
    Помогите разобраться с одним моментом. Есть один вопрос. Как правильно описать джисон если первый словарь идет как динамический - это айдишник, по которому и получается джисон с сервера. Проблема в том что он всегда разный и он по сути значение, а ключа нету. Я по разному пробовал но не получается. Спасибо заранее за помощь.

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Доброго времени суток) Можете пожалуйста написать пример и попробуем решить проблему вместе ?)

    • @fctrade
      @fctrade 2 роки тому

      @@SolveMeChannel Здравствуйте.
      json = {'158023': {'prices': {'xbox': {'LCPrice': '217,000', 'LCPrice2': '218,000', 'LCPrice3': '218,000',
      'LCPrice4': '219,000', 'LCPrice5': '220,000', 'updated': '5 mins ago',
      'MinPrice': '24,250', 'MaxPrice': '460,000', 'PRP': '44'},
      'ps': {'LCPrice': '276,000', 'LCPrice2': '278,000', 'LCPrice3': '280,000',
      'LCPrice4': '280,000', 'LCPrice5': '280,000', 'updated': '5 mins ago',
      'MinPrice': '30,000', 'MaxPrice': '550,000', 'PRP': '47'},
      'pc': {'LCPrice': '362,000', 'LCPrice2': '365,000', 'LCPrice3': '366,000',
      'LCPrice4': '369,000', 'LCPrice5': '369,000', 'updated': '11 mins ago',
      'MinPrice': '38,500', 'MaxPrice': '750,000', 'PRP': '45'}}}}
      интересует '158023' = это айдишники и они всегда разные

    • @fctrade
      @fctrade 2 роки тому

      он получается динамический и я вовсе не понимаю как его описать. Заранее спасибо за любую помощь!

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Можете пожалуйста написать мне этот пример на почту или в группу в телеграм? А то youtube удаляет комментарии некоторые :(

  • @СергейКапран-я7п
    @СергейКапран-я7п 2 роки тому

    Добрый день. Спасибо за лекции, очень актуально!
    Есть вопрос - может ли pydantic работать с "плавающими" секциями в json. Например family, name, middlename. Бывает что отчества нет или оно не указано, и поле то есть, то его нет.

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому +1

      Добрый день, в таком случае можно использовать значение по-умолчанию, к примеру:
      class Human(BaseModel):
      name: str
      last_name: str
      surname: str = None
      human = Human.parse_obj({
      "name": "Andrii",
      "last_name": "Shevchenko",
      "surname": "Sheva"
      })
      print(human.surname)
      human = Human.parse_obj({
      "name": "Andrii",
      "last_name": "Shevchenko"
      })
      print(human.surname)
      Если имени не будет, то ничего не произойдёт и в значении surname будет None, если есть, то будет соответственно то, что было передано. surname: str = None - эта конструкция как-раз и позволяет работать с необязательными полями (принцип тот же, как при описании аргументов которые может принимать метод/функция на вход). Так же вместо None, там может быть что угодно (число, массив, строка и т.д.), не рекомендовал бы только использовать пустую строку, так как нельзя будет потом понять, вам пришла пустая строка или это значение по-умолчанию, а так, вы можете создать валидацию на это поле, проверить что оно не None и если это так, делать какие-то проверки.

    • @СергейКапран-я7п
      @СергейКапран-я7п 2 роки тому

      @@SolveMeChannel Спасибо за быстрый и развёрнутый ответ

    • @alexsanchoss
      @alexsanchoss 2 роки тому

      @@SolveMeChannel а что делать если, например, поле зависит от какой-то логики? Например, поле surname показывается, если поле show_surname = true.
      У меня подобная ситуация сейчас. Думаю как решить. Не хочется все эти поля делать optional.

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому +1

      Alexander V. Привет :)
      Можно воспользоваться вот такой конструкцией:
      class Human(BaseModel):
      name: str
      last_name: str
      surname: str = None
      is_hide: bool
      @validator('is_hide')
      def validate_surname_showing(cls, hide_value, values):
      if hide_value is False and values.get('surname') is None:
      raise ValueError('Surname should be presented')
      return hide_value
      human = Human.parse_obj({
      "name": "Andrii",
      "last_name": "Shevchenko",
      "is_hide": True
      })
      Обязательно валидировать поле is_hide и в валидаторе дополнительно принимать все значения, после этого просто проверять значение поля is_hide и то, что было передано. Обрати внимание, что если мы например валидируем поле is_hide, то в параметр values попадут все значения которые в описании класса находятся выше него, если бы мы разместили surname ниже is_hide, то нам бы постоянно приходил None и валидатор бы фейлился. Это из-за того, что он валидирует всё построчно и параметры ниже валидируемого поля просто ещё не попали в обьект класса pydantic.

    • @alexsanchoss
      @alexsanchoss 2 роки тому

      @@SolveMeChannel спасибо)
      Позволю себе задать еще вопрос: как ты организовал логирование ошибок с Pydantic в контексте получения отчетов в связке с allure?
      У меня тест помечается как broken, а не failed в случае каких-то ошибок в валидации.
      Спасибо заранее)

  • @l7l7l7lful
    @l7l7l7lful 2 роки тому

    Я не внимательно смотрел видео или правда обещанного сравнения как бы эта валидация выглядела с использованием json schema не было?

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Добрый день, в этом видео ua-cam.com/video/6QjDW-p_F-o/v-deo.html показывал как с ней работать и уже в дальнейших видео показывал как работать с pydantic, так же , почему я отдаю предпочтение именно ему.

  • @bahruzaghalar3533
    @bahruzaghalar3533 2 роки тому

    You hide your currently edited file names and it's hard to copy something from your code.
    You can push your changes for each lesson as a separate branch as this guy did for his 7hours tutorial.
    ua-cam.com/video/c708Nf0cHrs/v-deo.html
    Channel super except for this issues

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Hello, thank you so much for your response. I've fixed the issue with displaying the current tab. The creation of separate branches for each lesson was as hard for me as it could be because all lessons have been published and it is almost impossible to copy symbol by symbol.
      One more thing about why I don't want to do that it is the main idea of the lessons project, I want to have some cookbook for our community in which they could find anything without searching the Internet for a quick start of automation.

  • @nutritionfacts8871
    @nutritionfacts8871 2 роки тому

    Зачем постоянно меняешь фрейм? Не пойму, усложнять то зачем

    • @SolveMeChannel
      @SolveMeChannel  2 роки тому

      Привет дружище, к сожалению, у меня были большие проблемы с расширением экрана и как следствие, его отображение в видео, каждое видео это логическая эволюция -___- В первом исправил консоль, теперь не видно табы, исправил табы, не видно консоль, поменял назад и делал так, чтобы было видно что я пишу в консольке, потом исправил размер шрифта и т.д.
      По этому, сорри, сейчас уже +- пришёл к чему-то адекватному, если что-то не видно или не получается, пиши, я постараюсь помочь)

    • @nutritionfacts8871
      @nutritionfacts8871 2 роки тому

      @@SolveMeChannel о спасибо большое не думал что ответишь. Сам недавно начал изучать автомейшн. Иногда работаю на Постмане, вручную ароверяю. Работаю на мануал тестинг. Спасибо за твои видео, многому научил. Удачи тебе и самые лучшие пожелания