<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Майя</title><author><name>Майя</name></author><id>https://teletype.in/atom/maya.work905</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/maya.work905?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/maya.work905?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-03T18:13:43.289Z</updated><entry><id>maya.work905:YNcxmNJe0Sm</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/YNcxmNJe0Sm?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Страна для удаленщиков, любителей Азии</title><published>2025-12-23T13:26:02.148Z</published><updated>2025-12-23T13:26:02.148Z</updated><summary type="html">🇮🇩 Индонезия — официально</summary><content type="html">
  &lt;h1 id=&quot;FMTM&quot;&gt;Визы, документы.&lt;/h1&gt;
  &lt;p id=&quot;Yglu&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;8Ldo&quot;&gt;🇮🇩 Индонезия — официально&lt;/p&gt;
  &lt;h2 id=&quot;0D4n&quot;&gt;Visitor Visa / e-VOA (туризм, временное пребывание)&lt;/h2&gt;
  &lt;ul id=&quot;jExq&quot;&gt;
    &lt;li id=&quot;7UGk&quot;&gt;&lt;strong&gt;Тип визы:&lt;/strong&gt; e-VOA / VOA (Visitor Visa)&lt;/li&gt;
    &lt;li id=&quot;xRa4&quot;&gt;&lt;strong&gt;Въезд:&lt;/strong&gt; single-entry&lt;/li&gt;
    &lt;li id=&quot;1NjP&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; 30 дней + 1 продление ещё на 30 (итого до 60)&lt;/li&gt;
    &lt;li id=&quot;8yGH&quot;&gt;&lt;strong&gt;Стоимость:&lt;/strong&gt; IDR 500,000&lt;/li&gt;
    &lt;li id=&quot;gDCG&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ❌ формально запрещена (серое использование на практике)&lt;/li&gt;
    &lt;li id=&quot;Ssmk&quot;&gt;&lt;strong&gt;Перевыпуск:&lt;/strong&gt; после выезда можно оформить снова, лимита «X раз в год» нет, но частые въезды = риск отказа&lt;/li&gt;
    &lt;li id=&quot;HPI8&quot;&gt;&lt;strong&gt;Оверстей:&lt;/strong&gt; IDR 1,000,000 за каждый день + депортация при серьёзном нарушении&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;KdBl&quot;&gt;Официальные источники&lt;/h3&gt;
  &lt;ul id=&quot;q2G2&quot;&gt;
    &lt;li id=&quot;j3G4&quot;&gt;Гос. визовый портал Индонезии (e-Visa / e-VOA):&lt;br /&gt;&lt;a href=&quot;https://evisa.imigrasi.go.id/front/info/evoa?utm_source=chatgpt.com&quot; target=&quot;_blank&quot;&gt;https://evisa.imigrasi.go.id/front/info/evoa&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;1ku1&quot;&gt;Иммиграционная служба Индонезии:&lt;br /&gt;&lt;a href=&quot;https://imigrasi.go.id/&quot; target=&quot;_blank&quot;&gt;https://imigrasi.go.id&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;knKX&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;6Gxu&quot;&gt;Может быть продлен каждый раз на 60 дней (2 месяца) до максимального общего срока пребывания 180 дней (6 месяцев).&lt;/p&gt;
  &lt;h2 id=&quot;9uFn&quot;&gt;Required Documents&lt;/h2&gt;
  &lt;p id=&quot;pjCG&quot;&gt;Scanned copies of:&lt;/p&gt;
  &lt;ol id=&quot;7Ud3&quot;&gt;
    &lt;li id=&quot;ppkb&quot;&gt;passport or valid travel document;&lt;/li&gt;
    &lt;li id=&quot;dZaE&quot;&gt;letter of guarantee from the same sponsor submitted when applying for the visa (if using a sponsor);&lt;/li&gt;
    &lt;li id=&quot;UTnx&quot;&gt;statement letter explaining the purpose and intention of staying in Indonesia.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;vPKG&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;vYRI&quot;&gt;Fees&lt;/h2&gt;
  &lt;ul id=&quot;AUkd&quot;&gt;
    &lt;li id=&quot;fO1D&quot;&gt;ITK for 30 days: Rp500,000 per application&lt;/li&gt;
    &lt;li id=&quot;Vlek&quot;&gt;ITK for 60 days: Rp2,000,000 per application&lt;/li&gt;
    &lt;li id=&quot;3OzO&quot;&gt;ITK for 180 days: Rp6,000,000 per application&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;W1Mj&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;ar3U&quot;&gt;долгую визу сложнее получать так как надо регистрировать там свою компанию&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;qSPl&quot;&gt;🇻🇳 Вьетнам — официально&lt;/h2&gt;
  &lt;h2 id=&quot;uJD7&quot;&gt;e-Visa (туризм / краткосрочное пребывание)&lt;/h2&gt;
  &lt;ul id=&quot;iIKw&quot;&gt;
    &lt;li id=&quot;H9w2&quot;&gt;&lt;strong&gt;Тип визы:&lt;/strong&gt; e-Visa&lt;/li&gt;
    &lt;li id=&quot;MY3C&quot;&gt;&lt;strong&gt;Въезд:&lt;/strong&gt; single или multiple&lt;/li&gt;
    &lt;li id=&quot;5gRa&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; до 90 дней&lt;/li&gt;
    &lt;li id=&quot;SxNs&quot;&gt;&lt;strong&gt;Стоимость:&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;0rpm&quot;&gt;
      &lt;li id=&quot;bda5&quot;&gt;$25 — single&lt;/li&gt;
      &lt;li id=&quot;9nZ0&quot;&gt;$50 — multiple&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;vjvG&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ❌ формально запрещена&lt;/li&gt;
    &lt;li id=&quot;nyAR&quot;&gt;&lt;strong&gt;Перевыпуск:&lt;/strong&gt; можно подавать повторно после выезда&lt;/li&gt;
    &lt;li id=&quot;shJg&quot;&gt;&lt;strong&gt;Оверстей:&lt;/strong&gt; штрафы + возможная депортация, санкции ужесточаются&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;CRq3&quot;&gt;Безвизовый въезд для РФ&lt;/h2&gt;
  &lt;ul id=&quot;HvMN&quot;&gt;
    &lt;li id=&quot;rH04&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; до 45 дней&lt;/li&gt;
    &lt;li id=&quot;ejIi&quot;&gt;&lt;strong&gt;Продление:&lt;/strong&gt; ❌ нельзя&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;rvBl&quot;&gt;Официальные источники&lt;/h3&gt;
  &lt;ul id=&quot;WW37&quot;&gt;
    &lt;li id=&quot;PIQU&quot;&gt;Посольство Вьетнама в РФ — безвиз:&lt;br /&gt;&lt;a href=&quot;https://vnembassy-moscow.mofa.gov.vn/ru-ru/Consular%20Services/Visa%20Exemption/Pages/default.aspx?utm_source=chatgpt.com&quot; target=&quot;_blank&quot;&gt;https://vnembassy-moscow.mofa.gov.vn/ru-ru/Consular%20Services/Visa%20Exemption/Pages/default.aspx&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;Gd39&quot;&gt;Официальный e-Visa портал правительства Вьетнама:&lt;br /&gt;&lt;a href=&quot;https://evisa.gov.vn/?utm_source=chatgpt.com&quot; target=&quot;_blank&quot;&gt;https://evisa.gov.vn&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;voHY&quot;&gt;🇹🇭 Таиланд — официально&lt;/h2&gt;
  &lt;h2 id=&quot;FuF5&quot;&gt;Visa Exemption (без визы)&lt;/h2&gt;
  &lt;ul id=&quot;KexK&quot;&gt;
    &lt;li id=&quot;iqYZ&quot;&gt;&lt;strong&gt;Для граждан РФ:&lt;/strong&gt; да&lt;/li&gt;
    &lt;li id=&quot;1Hj9&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; до 60 дней&lt;/li&gt;
    &lt;li id=&quot;4etT&quot;&gt;&lt;strong&gt;Ограничение:&lt;/strong&gt; не более 90 дней в течение 6 месяцев&lt;/li&gt;
    &lt;li id=&quot;UoQX&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ❌ формально запрещена&lt;/li&gt;
    &lt;li id=&quot;RHew&quot;&gt;&lt;strong&gt;Оверстей:&lt;/strong&gt; 500 THB/день, максимум 20,000 THB&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;JT5o&quot;&gt;Tourist Visa (TR)&lt;/h2&gt;
  &lt;ul id=&quot;jW8E&quot;&gt;
    &lt;li id=&quot;KojK&quot;&gt;&lt;strong&gt;Въезд:&lt;/strong&gt; single / multiple&lt;/li&gt;
    &lt;li id=&quot;BO5d&quot;&gt;&lt;strong&gt;Стоимость:&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;zOkk&quot;&gt;
      &lt;li id=&quot;MlpZ&quot;&gt;2,000 THB — single&lt;/li&gt;
      &lt;li id=&quot;4gRE&quot;&gt;5,000 THB — multiple&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;1YLQ&quot;&gt;&lt;strong&gt;Перевыпуск:&lt;/strong&gt; возможен, но частые визы → вопросы на границе&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;9E7N&quot;&gt;Destination Thailand Visa (DTV) — лучший вариант под удалёнку&lt;/h2&gt;
  &lt;ul id=&quot;6oNC&quot;&gt;
    &lt;li id=&quot;wIrl&quot;&gt;&lt;strong&gt;Тип:&lt;/strong&gt; long-stay / workcation&lt;/li&gt;
    &lt;li id=&quot;mlaR&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ✅ разрешена при работе на иностранного работодателя&lt;/li&gt;
    &lt;li id=&quot;CJUj&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; долгосрочный (зависит от категории)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;fcig&quot;&gt;Официальные источники&lt;/h3&gt;
  &lt;ul id=&quot;CrAK&quot;&gt;
    &lt;li id=&quot;CjHn&quot;&gt;Посольство Таиланда в Москве — визы:&lt;br /&gt;&lt;a href=&quot;true&quot;&gt;https://moscow.thaiembassy.org/en/publicservice/98912-general-visa-information&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;k7Sj&quot;&gt;Посольство Таиланда (пример виз TR):&lt;br /&gt;&lt;a href=&quot;https://rtehanoi.thaiembassy.org/th/publicservice/25691-tourist-visa&quot; target=&quot;_blank&quot;&gt;https://rtehanoi.thaiembassy.org/th/publicservice/25691-tourist-visa&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;y2QE&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;7OaA&quot;&gt;&lt;strong&gt;2.&lt;u&gt; Условия получения туристической визы&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;JqIk&quot;&gt;2.1 Туристическая виза действительна в течение 3 месяцев с даты выдачи. Путешественники должны въехать в страну в течение указанного 3-месячного периода.&lt;/p&gt;
  &lt;p id=&quot;lDJC&quot;&gt;2.2 Путешественникам будет разрешено оставаться до 60 дней, считая с даты въезда. Продление пребывания возможно еще на 30 дней, при этом максимальный срок пребывания составляет 90 дней, считая с даты въезда. Путешественники должны связаться с Управлением Иммиграционного бюро (&lt;a href=&quot;http://www.immigration.go.th/&quot; target=&quot;_blank&quot;&gt;http://www.immigration.go.th&lt;/a&gt;) для получения дополнительной информации. Продление визы осуществляется исключительно по усмотрению сотрудника иммиграционной службы.&lt;/p&gt;
  &lt;p id=&quot;f3Ef&quot;&gt;2.3 Если владелец туристической визы нарушает условия въезда (например, если он/она занимается деятельностью, связанной с работой), разрешение на пребывание будет аннулировано, и ему/ей будет запрещено въезжать в Таиланд в будущем.&lt;/p&gt;
  &lt;p id=&quot;JURt&quot;&gt;&lt;strong&gt;3.&lt;u&gt; Необходимые документы для подачи заявления на получение туристической визы&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;x0to&quot;&gt;3.1 Паспорт или проездной документ со сроком действия не менее 6 месяцев&lt;/p&gt;
  &lt;p id=&quot;4AUU&quot;&gt;3.2 Одна заполненная визовая анкета&lt;/p&gt;
  &lt;p id=&quot;ArZL&quot;&gt;3.3 Одна (01) недавняя фотография (размер 3,5 x 4,5 см.) прикрепляется к форме заявления на визу&lt;/p&gt;
  &lt;p id=&quot;2zOd&quot;&gt;3.4 Доказательства транспортировки&lt;/p&gt;
  &lt;ul id=&quot;Oq3L&quot;&gt;
    &lt;li id=&quot;C9fg&quot;&gt;Маршрут полета для билета туда и ОБРАТНО (на тайском или английском языках)&lt;/li&gt;
    &lt;li id=&quot;l7Zd&quot;&gt;В бронировании/маршрута должно быть указано полное имя заявителя, дата и время прибытия и вылета, а также данные о рейсе&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;TPrf&quot;&gt;(2) Заявитель, проживающий в арендованном жилье:&lt;/p&gt;
  &lt;ul id=&quot;0zIE&quot;&gt;
    &lt;li id=&quot;Aq1l&quot;&gt;Копия договора аренды&lt;/li&gt;
    &lt;li id=&quot;ZxMp&quot;&gt;Копия регистрации дома (если таковая есть)&lt;/li&gt;
    &lt;li id=&quot;LDpQ&quot;&gt;Копия владельца дома и удостоверения личности арендодателя (для граждан Таиланда) или паспорта и разрешения на работу (для иностранцев) арендодателя&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Cf4J&quot;&gt;🇵🇭 Филиппины — официально&lt;/h2&gt;
  &lt;h2 id=&quot;9iOV&quot;&gt;Безвизовый въезд&lt;/h2&gt;
  &lt;ul id=&quot;XKaV&quot;&gt;
    &lt;li id=&quot;MiqZ&quot;&gt;&lt;strong&gt;Для РФ:&lt;/strong&gt; да&lt;/li&gt;
    &lt;li id=&quot;Acwc&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; 30 дней&lt;/li&gt;
    &lt;li id=&quot;xjuB&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ❌ формально запрещена&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;7nUc&quot;&gt;Продление пребывания (ключевая фишка Филиппин)&lt;/h2&gt;
  &lt;ul id=&quot;6JXt&quot;&gt;
    &lt;li id=&quot;BlEw&quot;&gt;&lt;strong&gt;Продления:&lt;/strong&gt; 29 дней → 1 / 2 / 6 месяцев&lt;/li&gt;
    &lt;li id=&quot;Uszj&quot;&gt;&lt;strong&gt;Максимум:&lt;/strong&gt; до 36 месяцев без выезда&lt;/li&gt;
    &lt;li id=&quot;rMT2&quot;&gt;&lt;strong&gt;Перевыпуск:&lt;/strong&gt; не нужен — всё продлевается внутри страны&lt;/li&gt;
    &lt;li id=&quot;OcEu&quot;&gt;&lt;strong&gt;Оверстей:&lt;/strong&gt; штраф от PHP 500/месяц + обязательная легализация&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;gMAc&quot;&gt;Официальные источники&lt;/h3&gt;
  &lt;ul id=&quot;jmAP&quot;&gt;
    &lt;li id=&quot;9EqP&quot;&gt;Посольство Филиппин (консульский раздел):&lt;br /&gt;&lt;a href=&quot;https://philippines.mid.ru/en/consular-services/?utm_source=chatgpt.com&quot; target=&quot;_blank&quot;&gt;https://philippines.mid.ru/en/consular-services/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;FGDX&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Sdat&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;ZQ6s&quot;&gt;&lt;a href=&quot;https://philippines.mid.ru/en/consular-services/bde8ec42fe5a32ceb4662fe3efa72830&quot; target=&quot;_blank&quot;&gt;ТУРИСТИЧЕСКАЯ ВИЗА&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;Uwu8&quot;&gt;Требования:&lt;/p&gt;
  &lt;ol id=&quot;9m0h&quot;&gt;
    &lt;li id=&quot;BqZm&quot;&gt;Заявление (заполненное на &lt;a href=&quot;https://visa.kdmid.ru/&quot; target=&quot;_blank&quot;&gt;https://visa.kdmid.ru/ &lt;/a&gt;и распечатанное) с подписью Заявителя и фотографией (3,5x4,5);&lt;/li&gt;
    &lt;li id=&quot;HGz5&quot;&gt;Паспорт, действительный не менее 6 месяцев с даты истечения срока действия визы;&lt;/li&gt;
    &lt;li id=&quot;7ksb&quot;&gt;Ваучер и подтверждение от авторизованного российского туристического агентства;&lt;/li&gt;
    &lt;li id=&quot;aQRd&quot;&gt;&lt;strong&gt;Вид на жительство / долгосрочная виза (или другая), &lt;/strong&gt;подтверждающая право на пребывание в Республике Филиппины на срок более 180 дней - если заявитель не является гражданином Республики Филиппины.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;gkIc&quot;&gt;🇯🇵 Япония — официально&lt;/h2&gt;
  &lt;h2 id=&quot;l542&quot;&gt;Short-Term Stay Visa (single-entry)&lt;/h2&gt;
  &lt;ul id=&quot;WZ24&quot;&gt;
    &lt;li id=&quot;xpO9&quot;&gt;&lt;strong&gt;Тип:&lt;/strong&gt; краткосрочная виза&lt;/li&gt;
    &lt;li id=&quot;WyJ4&quot;&gt;&lt;strong&gt;Срок:&lt;/strong&gt; до 90 дней&lt;/li&gt;
    &lt;li id=&quot;YuSa&quot;&gt;&lt;strong&gt;Стоимость для РФ:&lt;/strong&gt; 0 (по взаимности)&lt;/li&gt;
    &lt;li id=&quot;NO4c&quot;&gt;&lt;strong&gt;Удалённая работа:&lt;/strong&gt; ❌ строго запрещена&lt;/li&gt;
    &lt;li id=&quot;I9o2&quot;&gt;&lt;strong&gt;Перевыпуск:&lt;/strong&gt; возможен, но частые поездки = высокий риск отказа&lt;/li&gt;
    &lt;li id=&quot;ayj5&quot;&gt;&lt;strong&gt;Оверстей:&lt;/strong&gt; до 3 лет тюрьмы или штраф до 3 млн иен + бан&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;jlTd&quot;&gt;Официальные источники&lt;/h3&gt;
  &lt;ul id=&quot;I011&quot;&gt;
    &lt;li id=&quot;QoXC&quot;&gt;МИД Японии — визы для граждан РФ:&lt;br /&gt;&lt;a href=&quot;https://www.mofa.go.jp/j_info/visit/visa/short/russia.html?utm_source=chatgpt.com&quot; target=&quot;_blank&quot;&gt;https://www.mofa.go.jp/j_info/visit/visa/short/russia.html&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;36Ln&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;VNAT&quot;&gt;список документів по ссыпке &lt;a href=&quot;https://www.ru.emb-japan.go.jp/itpr_ja/tourism2022.html&quot; target=&quot;_blank&quot;&gt;https://www.ru.emb-japan.go.jp/itpr_ja/tourism2022.html&lt;/a&gt;&lt;/p&gt;
  &lt;hr /&gt;

</content></entry><entry><id>maya.work905:FLdlQkpJXC4</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/FLdlQkpJXC4?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Брокер сообщений, логи</title><published>2025-10-20T08:57:42.280Z</published><updated>2025-11-25T15:09:47.040Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/e4/8f/e48fe931-5a7f-439c-8cec-8f9ac6f47948.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/7a7/9ac/cda/7a79accda66a4a58c72bf21f4f64a604.png&quot;&gt;Что такое брокер сообщений и для чего он нужен?</summary><content type="html">
  &lt;h2 id=&quot;eFRo&quot;&gt;📩 Что такое брокер сообщений и для чего он нужен?&lt;/h2&gt;
  &lt;figure id=&quot;hhOz&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/75/97/759791fa-d1a0-476e-8d3c-7f45e97c323c.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;2ZpI&quot;&gt;Брокер сообщений — это компонент архитектуры, который выступает посредником между различными частями системы. Он помогает системам обмениваться данными, снимая нагрузку с веб-сервисов, так как им не нужно напрямую пересылать сообщения друг другу.&lt;/p&gt;
  &lt;p id=&quot;GlS5&quot;&gt;В брокере сообщений есть две ключевые роли:&lt;/p&gt;
  &lt;ul id=&quot;HME5&quot;&gt;
    &lt;li id=&quot;jKqx&quot;&gt;&lt;strong&gt;Producer (издатель)&lt;/strong&gt; 📝 — создаёт и отправляет сообщения.&lt;/li&gt;
    &lt;li id=&quot;xYA9&quot;&gt;&lt;strong&gt;Consumer (потребитель/подписчик)&lt;/strong&gt; 📥 — получает и обрабатывает сообщения.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;R2NL&quot;&gt;Сообщения могут передаваться двумя способами:&lt;/p&gt;
  &lt;ol id=&quot;6krv&quot;&gt;
    &lt;li id=&quot;DPC6&quot;&gt;&lt;strong&gt;Прямо от отправителя к получателю&lt;/strong&gt; — каждое сообщение используется только один раз.&lt;/li&gt;
    &lt;li id=&quot;9pdD&quot;&gt;&lt;strong&gt;Схема публикации/подписки (Pub/Sub)&lt;/strong&gt; 🔄 — продюсер публикует сообщение в &lt;strong&gt;топик&lt;/strong&gt;, а все подписчики получают его. Так можно строить распределение задач между подписчиками, где каждый получает только свои сообщения.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;BJTP&quot;&gt;⚡ Преимущества брокеров сообщений перед API:&lt;/h3&gt;
  &lt;ul id=&quot;QawP&quot;&gt;
    &lt;li id=&quot;DtAO&quot;&gt;Асинхронная передача данных, не блокирующая работу системы.&lt;/li&gt;
    &lt;li id=&quot;gls5&quot;&gt;Повышение производительности за счёт разгрузки сервисов.&lt;/li&gt;
    &lt;li id=&quot;xlg3&quot;&gt;Надёжная доставка с повторной отправкой и маршрутизацией сообщений.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;R8sg&quot;&gt;❌ Недостатки:&lt;/h3&gt;
  &lt;ul id=&quot;GG6W&quot;&gt;
    &lt;li id=&quot;89x9&quot;&gt;Усложнение архитектуры.&lt;/li&gt;
    &lt;li id=&quot;wyTd&quot;&gt;Возможные проблемы с консистентностью данных.&lt;/li&gt;
    &lt;li id=&quot;pLxz&quot;&gt;Отладка распределённой системы сложнее.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;x2UP&quot;&gt;🛠 Когда полезны:&lt;/h3&gt;
  &lt;ul id=&quot;sw9G&quot;&gt;
    &lt;li id=&quot;xL0P&quot;&gt;Долгие и ресурсоёмкие задачи.&lt;/li&gt;
    &lt;li id=&quot;BEFq&quot;&gt;Микросервисы для координации сервисов через топики.&lt;/li&gt;
    &lt;li id=&quot;h0sU&quot;&gt;Мобильные приложения с push-уведомлениями.&lt;/li&gt;
    &lt;li id=&quot;dNUL&quot;&gt;Транзакционные системы с последовательными этапами обработки.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;LsZD&quot;&gt;🏭 Apache Kafka: продюсеры, брокеры, консумеры&lt;/h2&gt;
  &lt;h3 id=&quot;jiRz&quot;&gt;Как устроен Kafka&lt;/h3&gt;
  &lt;ul id=&quot;Qp5a&quot;&gt;
    &lt;li id=&quot;Izjc&quot;&gt;&lt;strong&gt;Producer&lt;/strong&gt; 📝 — приложение, отправляющее сообщения в кластер Kafka.&lt;/li&gt;
    &lt;li id=&quot;TWyc&quot;&gt;&lt;strong&gt;Broker&lt;/strong&gt; 💻 — сервер, который хранит данные и распределяет их между консумерами.&lt;/li&gt;
    &lt;li id=&quot;s7IC&quot;&gt;&lt;strong&gt;Consumer&lt;/strong&gt; 📥 — приложение, читающее сообщения из Kafka.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;BYec&quot;&gt;Kafka работает через &lt;strong&gt;логи&lt;/strong&gt; 📜 — упорядоченные по времени записи событий. Каждое событие добавляется в конец лога и остаётся неизменным.&lt;/p&gt;
  &lt;h3 id=&quot;2WIC&quot;&gt;Топики, партиции и сегменты&lt;/h3&gt;
  &lt;ul id=&quot;foJy&quot;&gt;
    &lt;li id=&quot;0YTI&quot;&gt;&lt;strong&gt;Топик&lt;/strong&gt; 🗂 — логическая группа сообщений (например, статусы заказов).&lt;/li&gt;
    &lt;li id=&quot;cUS1&quot;&gt;&lt;strong&gt;Партиции&lt;/strong&gt; 🔹 — деление топика на части для масштабирования. Каждая партиция — строго упорядоченный лог.&lt;/li&gt;
    &lt;li id=&quot;QaUo&quot;&gt;&lt;strong&gt;Сегменты&lt;/strong&gt; 📄 — файлы на диске, в которых хранятся сообщения партиций.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;xSct&quot;&gt;Каждое сообщение имеет &lt;strong&gt;offset&lt;/strong&gt; — порядковый номер. Партиции могут &lt;strong&gt;реплицироваться&lt;/strong&gt; для отказоустойчивости.&lt;/p&gt;
  &lt;h3 id=&quot;FgUm&quot;&gt;Продюсеры и партицирование&lt;/h3&gt;
  &lt;p id=&quot;zmvh&quot;&gt;Продюсер сам выбирает, в какую партицию писать сообщение:&lt;/p&gt;
  &lt;ul id=&quot;XX30&quot;&gt;
    &lt;li id=&quot;KTjH&quot;&gt;По ключу (hash-based) 🔑 — гарантирует порядок сообщений для одного ключа.&lt;/li&gt;
    &lt;li id=&quot;F7Kt&quot;&gt;Round-robin 🔄 — равномерное распределение сообщений без гарантии порядка.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;4Lhe&quot;&gt;Семантики доставки сообщений&lt;/h3&gt;
  &lt;ul id=&quot;F2l3&quot;&gt;
    &lt;li id=&quot;roJS&quot;&gt;&lt;strong&gt;At-most-once&lt;/strong&gt; ❌ — можно потерять сообщения, но дубликатов нет.&lt;/li&gt;
    &lt;li id=&quot;dh3w&quot;&gt;&lt;strong&gt;At-least-once&lt;/strong&gt; ✅ — сообщения не теряются, но возможны дубликаты.&lt;/li&gt;
    &lt;li id=&quot;PzQY&quot;&gt;&lt;strong&gt;Exactly-once&lt;/strong&gt; 🎯 — каждое сообщение доставлено ровно один раз.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;nYx6&quot;&gt;Консумеры и консумер-группы&lt;/h3&gt;
  &lt;ul id=&quot;aDlf&quot;&gt;
    &lt;li id=&quot;wo3o&quot;&gt;&lt;strong&gt;Consumer&lt;/strong&gt; 📥 — читает сообщения из партиций.&lt;/li&gt;
    &lt;li id=&quot;zOJH&quot;&gt;&lt;strong&gt;Consumer group&lt;/strong&gt; 👥 — несколько консумеров читают партиции кооперативно.&lt;/li&gt;
    &lt;li id=&quot;fJnE&quot;&gt;&lt;strong&gt;Heartbeat и session timeout&lt;/strong&gt; ⏱ — проверка живости консумеров.&lt;/li&gt;
    &lt;li id=&quot;83jY&quot;&gt;&lt;strong&gt;Ребалансировка&lt;/strong&gt; 🔄 — перераспределение партиций при добавлении/удалении консумеров.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;ATYD&quot;&gt;📝 Логи: что это и зачем смотреть&lt;/h2&gt;
  &lt;figure id=&quot;QvPR&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0d/fc/0dfcac6b-94ae-4e21-a35f-b20972d41c1c.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;fkur&quot;&gt;Что такое логи&lt;/h3&gt;
  &lt;p id=&quot;grTi&quot;&gt;Логи — это записи событий и сообщений системы. Они помогают понять, что происходит внутри приложения.&lt;/p&gt;
  &lt;h3 id=&quot;Qwi9&quot;&gt;Когда смотреть логи&lt;/h3&gt;
  &lt;ul id=&quot;nclm&quot;&gt;
    &lt;li id=&quot;81T0&quot;&gt;Тестирование новой функциональности 🧪&lt;/li&gt;
    &lt;li id=&quot;ZBWN&quot;&gt;Регрессионное тестирование 🔄&lt;/li&gt;
    &lt;li id=&quot;bIN1&quot;&gt;Проверка взаимодействия с внешними системами 🌐&lt;/li&gt;
    &lt;li id=&quot;uK1t&quot;&gt;Отладка ошибок 🐞&lt;/li&gt;
    &lt;li id=&quot;nPFC&quot;&gt;Оценка производительности ⚡&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;tzia&quot;&gt;Уровни логирования&lt;/h3&gt;
  &lt;ul id=&quot;GpC4&quot;&gt;
    &lt;li id=&quot;58d3&quot;&gt;&lt;strong&gt;FATAL&lt;/strong&gt; 💀 — критическая ошибка, ведущая к завершению программы.&lt;/li&gt;
    &lt;li id=&quot;1jLI&quot;&gt;&lt;strong&gt;ERROR&lt;/strong&gt; ❌ — ошибка, требующая вмешательства.&lt;/li&gt;
    &lt;li id=&quot;hRBv&quot;&gt;&lt;strong&gt;WARN&lt;/strong&gt; ⚠️ — предупреждение о потенциальной проблеме.&lt;/li&gt;
    &lt;li id=&quot;CVxN&quot;&gt;&lt;strong&gt;INFO&lt;/strong&gt; ℹ️ — информация о ходе работы.&lt;/li&gt;
    &lt;li id=&quot;DbJK&quot;&gt;&lt;strong&gt;DEBUG&lt;/strong&gt; 🐛 — подробные данные для отладки.&lt;/li&gt;
    &lt;li id=&quot;9SsR&quot;&gt;&lt;strong&gt;TRACE&lt;/strong&gt; 🔍 — максимально подробная информация, шаги выполнения.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;Xzkl&quot;&gt;Виды логов&lt;/h3&gt;
  &lt;ul id=&quot;D0a3&quot;&gt;
    &lt;li id=&quot;rt9O&quot;&gt;&lt;strong&gt;Application logs&lt;/strong&gt; 🖥 — события внутри приложения.&lt;/li&gt;
    &lt;li id=&quot;EXZk&quot;&gt;&lt;strong&gt;Server logs&lt;/strong&gt; 🖧 — ошибки и запросы на сервере.&lt;/li&gt;
    &lt;ul id=&quot;O1v5&quot;&gt;
      &lt;li id=&quot;t5sb&quot;&gt;Error logs ❌&lt;/li&gt;
      &lt;li id=&quot;d8FV&quot;&gt;Access logs 🔑&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;vgmg&quot;&gt;&lt;strong&gt;System logs&lt;/strong&gt; ⚙️ — работа ОС и системные события.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;0uM6&quot;&gt;Что хранится в логах&lt;/h3&gt;
  &lt;ul id=&quot;xPct&quot;&gt;
    &lt;li id=&quot;le2L&quot;&gt;Время и дата события 🕒&lt;/li&gt;
    &lt;li id=&quot;9XQ9&quot;&gt;Уровень логирования&lt;/li&gt;
    &lt;li id=&quot;AShx&quot;&gt;Контекст системы или модуля 🏷&lt;/li&gt;
    &lt;li id=&quot;XCf7&quot;&gt;Текст сообщения&lt;/li&gt;
    &lt;li id=&quot;Ae4t&quot;&gt;Стек вызовов при ошибках 🧾&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;g5dp&quot;&gt;🔧 Инструменты для просмотра логов&lt;/h2&gt;
  &lt;ul id=&quot;ubN5&quot;&gt;
    &lt;li id=&quot;hiy0&quot;&gt;&lt;strong&gt;Lens&lt;/strong&gt; 👓 — визуализация логов.&lt;/li&gt;
    &lt;li id=&quot;Zmbn&quot;&gt;&lt;strong&gt;Grafana Loki&lt;/strong&gt; 📊 — мониторинг и поиск по логам в реальном времени.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;PQME&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;f1GJ&quot;&gt;Почитай тут &lt;a href=&quot;https://habr.com/ru/companies/yandex_praktikum/articles/739058/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/companies/yandex_praktikum/articles/739058/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;CggG&quot;&gt;А посмотри вот здесь:&lt;br /&gt;&lt;a href=&quot;https://youtu.be/keBrfAhFiP4?si=PCnASeFENyotAuDn&quot; target=&quot;_blank&quot;&gt;https://youtu.be/keBrfAhFiP4?si=PCnASeFENyotAuDn&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:Hot0QANAUZC</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/Hot0QANAUZC?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Базы данных</title><published>2025-10-20T08:35:53.125Z</published><updated>2025-11-25T15:00:56.434Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/5d/eb/5deb14b4-b4a0-40eb-af69-6d48a2934be3.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://skillbox.ru/upload/setka_images/11354331012023_5c20dcbcfbab07ab6c2df7e27444d5ac2afca569.png&quot;&gt;Какие базы данных называются реляционными?</summary><content type="html">
  &lt;h1 id=&quot;PZJw&quot;&gt;🔹 Реляционные базы данных (RDB)&lt;/h1&gt;
  &lt;figure id=&quot;8oOq&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/df/77/df77ee37-d44a-4d54-9c81-13b6b92760eb.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;MU2L&quot;&gt;1️⃣ Что такое реляционная база данных&lt;/h3&gt;
  &lt;ul id=&quot;Mszd&quot;&gt;
    &lt;li id=&quot;V3ZS&quot;&gt;&lt;strong&gt;Определение:&lt;/strong&gt; база данных, где данные хранятся в таблицах, связанные между собой через ключи.&lt;/li&gt;
    &lt;li id=&quot;Ukkd&quot;&gt;&lt;strong&gt;Основные возможности:&lt;/strong&gt; гибкие сложные запросы к нескольким таблицам одновременно.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;WyWG&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/5e/e3/5ee3a705-c686-49c4-8681-db759eed65b7.png&quot; width=&quot;1566&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;f90e&quot;&gt;3️⃣ Первичный и внешний ключи&lt;/h3&gt;
  &lt;ul id=&quot;qW8Z&quot;&gt;
    &lt;li id=&quot;kswq&quot;&gt;&lt;strong&gt;Первичный ключ (Primary Key)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;tW1M&quot;&gt;
      &lt;li id=&quot;bMUc&quot;&gt;Уникальный идентификатор записи.&lt;/li&gt;
      &lt;li id=&quot;1VJy&quot;&gt;Не может быть NULL.&lt;/li&gt;
      &lt;li id=&quot;Whpg&quot;&gt;Обеспечивает однозначную идентификацию строки.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;UtuF&quot;&gt;&lt;strong&gt;Внешний ключ (Foreign Key)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;efJx&quot;&gt;
      &lt;li id=&quot;fAlN&quot;&gt;Ссылка на первичный ключ другой таблицы.&lt;/li&gt;
      &lt;li id=&quot;NEzP&quot;&gt;Позволяет связывать таблицы между собой.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;Grd9&quot;&gt;&lt;strong&gt;Родительский ключ (Parent Key)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;hTai&quot;&gt;
      &lt;li id=&quot;fjlK&quot;&gt;Первичный ключ, на который ссылается внешний ключ.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;vDof&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/14/7f/147f1367-9f98-4e21-98a6-a65eb56b8d31.png&quot; width=&quot;1566&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;Tprf&quot;&gt;5️⃣ Нормализация&lt;/h3&gt;
  &lt;ul id=&quot;hLYe&quot;&gt;
    &lt;li id=&quot;0xon&quot;&gt;Разделение таблицы на несколько, чтобы:&lt;/li&gt;
    &lt;ul id=&quot;qxwH&quot;&gt;
      &lt;li id=&quot;CILq&quot;&gt;Исключить дублирование данных&lt;/li&gt;
      &lt;li id=&quot;xDIK&quot;&gt;Присвоить уникальные ключи для каждой записи&lt;/li&gt;
      &lt;li id=&quot;uQu7&quot;&gt;Обновления происходили только один раз&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;AqMZ&quot;&gt;&lt;strong&gt;Нормальные формы:&lt;/strong&gt; 1NF → 2NF → 3NF → … → 6NF&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;NkQX&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt; таблица подрядчиков и клиентов разбита так, чтобы изменения телефона вносились только один раз.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;qRHC&quot;&gt;🔹 SQL (Structured Query Language)&lt;/h1&gt;
  &lt;h3 id=&quot;YMiO&quot;&gt;1️⃣ Определение&lt;/h3&gt;
  &lt;ul id=&quot;FcPk&quot;&gt;
    &lt;li id=&quot;5Bgr&quot;&gt;&lt;strong&gt;SQL&lt;/strong&gt; — язык для работы с реляционными базами данных.&lt;/li&gt;
    &lt;li id=&quot;xxy6&quot;&gt;Позволяет:&lt;/li&gt;
    &lt;ul id=&quot;jQIl&quot;&gt;
      &lt;li id=&quot;bRJN&quot;&gt;создавать таблицы и базы данных&lt;/li&gt;
      &lt;li id=&quot;6LNr&quot;&gt;добавлять, изменять, удалять и извлекать данные&lt;/li&gt;
      &lt;li id=&quot;o7PE&quot;&gt;управлять доступом&lt;/li&gt;
      &lt;li id=&quot;Dc9f&quot;&gt;работать с транзакциями&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;zHIO&quot;&gt;&lt;strong&gt;Важно:&lt;/strong&gt; SQL — декларативный язык: вы описываете, что хотите получить, а не как это реализовать.&lt;/p&gt;
  &lt;p id=&quot;2D2P&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;YZCq&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/46/b5/46b5cf3d-98e2-49ce-a432-f3657408b4b4.png&quot; width=&quot;1566&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;2zZO&quot;&gt;3️⃣ Основные операции SQL&lt;/h2&gt;
  &lt;ul id=&quot;DSgX&quot;&gt;
    &lt;li id=&quot;Dqq6&quot;&gt;&lt;strong&gt;INSERT&lt;/strong&gt; — добавить запись&lt;/li&gt;
    &lt;li id=&quot;2VHb&quot;&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; — изменить запись&lt;/li&gt;
    &lt;li id=&quot;BfNc&quot;&gt;&lt;strong&gt;DELETE&lt;/strong&gt; — удалить запись&lt;/li&gt;
    &lt;li id=&quot;F3a4&quot;&gt;&lt;strong&gt;SELECT&lt;/strong&gt; — выбрать данные&lt;/li&gt;
    &lt;li id=&quot;dytq&quot;&gt;&lt;strong&gt;ORDER BY&lt;/strong&gt; — сортировка&lt;/li&gt;
    &lt;li id=&quot;hP0f&quot;&gt;&lt;strong&gt;DISTINCT&lt;/strong&gt; — уникальные значения&lt;/li&gt;
    &lt;li id=&quot;YXHA&quot;&gt;&lt;strong&gt;COUNT, SUM&lt;/strong&gt; — агрегатные функции&lt;/li&gt;
    &lt;li id=&quot;skG0&quot;&gt;&lt;strong&gt;LIMIT&lt;/strong&gt; — ограничение числа результатов&lt;/li&gt;
    &lt;li id=&quot;F42t&quot;&gt;&lt;strong&gt;JOIN&lt;/strong&gt; — объединение таблиц&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;qSz3&quot;&gt;4️⃣ Примеры запросов&lt;/h2&gt;
  &lt;h3 id=&quot;BTTI&quot;&gt;4.1 Таблица Users&lt;/h3&gt;
  &lt;pre id=&quot;WIBd&quot;&gt;-- Вывести всех пользователей с именем &amp;quot;Олег&amp;quot;, сортировка по id
SELECT * FROM Users
WHERE name = &amp;#x27;Олег&amp;#x27;
ORDER BY id;
&lt;/pre&gt;
  &lt;h3 id=&quot;j1NF&quot;&gt;4.2 Таблица Orders&lt;/h3&gt;
  &lt;pre id=&quot;MHuc&quot;&gt;-- Посчитать количество заказов с оплатой &amp;quot;online&amp;quot;
SELECT COUNT(*) FROM Orders
WHERE payment = &amp;#x27;online&amp;#x27;;
&lt;/pre&gt;
  &lt;h3 id=&quot;TxbS&quot;&gt;4.3 JOIN с условиями&lt;/h3&gt;
  &lt;pre id=&quot;VO7g&quot;&gt;-- Выбрать все заказы пользователей из города &amp;quot;Saratov&amp;quot;
-- Вариант с JOIN
SELECT o.*
FROM Orders o
JOIN Users u ON o.user_id = u.id
WHERE u.city = &amp;#x27;Saratov&amp;#x27;;

-- Вариант с вложенным SELECT
SELECT * FROM Orders
WHERE user_id IN (
    SELECT id FROM Users WHERE city = &amp;#x27;Saratov&amp;#x27;
);
&lt;/pre&gt;
  &lt;h3 id=&quot;MNqb&quot;&gt;4.4 Соединение трёх таблиц&lt;/h3&gt;
  &lt;pre id=&quot;uBHD&quot;&gt;SELECT *
FROM Orders o
JOIN Users u ON o.user_id = u.id
JOIN Products p ON o.product_id = p.id;
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;3Kv1&quot;&gt;5️⃣ Практика&lt;/h3&gt;
  &lt;ul id=&quot;5PBX&quot;&gt;
    &lt;li id=&quot;nV71&quot;&gt;Использовать &lt;strong&gt;Postman, DBeaver&lt;/strong&gt; или аналогичные инструменты.&lt;/li&gt;
    &lt;li id=&quot;DefR&quot;&gt;Создать локальную БД и таблицы Users и Orders, заполнить тестовыми данными.&lt;/li&gt;
    &lt;li id=&quot;dxjG&quot;&gt;Пробовать все виды запросов, включая JOIN, агрегатные функции и фильтры.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;7WZh&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ac/e0/ace0e049-2bfe-4e78-8f06-4e52f2b3a072.png&quot; width=&quot;1566&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;jHSg&quot;&gt;Посмотри еще тут &lt;/p&gt;
  &lt;p id=&quot;zLlL&quot;&gt;&lt;a href=&quot;https://youtu.be/k8jXX7E_Wkg?si=LJBwHKevI4a314es&quot; target=&quot;_blank&quot;&gt;https://youtu.be/k8jXX7E_Wkg?si=LJBwHKevI4a314es&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;aSmW&quot;&gt;Тут инфа по тренажерам &lt;/p&gt;
  &lt;p id=&quot;FARg&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/943924/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/articles/943924/&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:4iB7MtPaQO0</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/4iB7MtPaQO0?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>HTTP-запросы</title><published>2025-10-20T08:25:40.638Z</published><updated>2025-11-25T14:51:40.550Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/5e/de/5ede5ca5-8ac9-440c-a638-9d4976e9f98d.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://selectel.ru/blog/wp-content/uploads/2022/06/image-1.png&quot;&gt;В чём отличие HTTP от HTTPS?</summary><content type="html">
  &lt;h1 id=&quot;e5Og&quot;&gt;🔹 HTTP-запросы: структура, методы, коды состояния&lt;/h1&gt;
  &lt;figure id=&quot;CL7q&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/dc/c5/dcc59f5d-1c22-42a6-bc2b-90c70e5d8eaa.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;oumd&quot;&gt;1️⃣ Базовые понятия HTTP&lt;/h2&gt;
  &lt;ul id=&quot;qUp0&quot;&gt;
    &lt;li id=&quot;V36A&quot;&gt;&lt;strong&gt;HTTP (HyperText Transfer Protocol)&lt;/strong&gt; — протокол прикладного уровня для передачи гипертекста и доступа к ресурсам веба.&lt;/li&gt;
    &lt;li id=&quot;BNNf&quot;&gt;&lt;strong&gt;Участники:&lt;/strong&gt;&lt;/li&gt;
    &lt;ol id=&quot;OQWl&quot;&gt;
      &lt;li id=&quot;xdzD&quot;&gt;&lt;strong&gt;Клиент&lt;/strong&gt; — запрашивает ресурс.&lt;/li&gt;
      &lt;li id=&quot;wg5r&quot;&gt;&lt;strong&gt;Сервер&lt;/strong&gt; — обрабатывает запрос и возвращает ресурс.&lt;/li&gt;
    &lt;/ol&gt;
    &lt;li id=&quot;17E1&quot;&gt;&lt;strong&gt;Порт по умолчанию:&lt;/strong&gt; 80 (HTTP), 443 (HTTPS).&lt;/li&gt;
    &lt;li id=&quot;EWgj&quot;&gt;&lt;strong&gt;Спецификация:&lt;/strong&gt; RFC 2616. Популярные версии: HTTP/1.1 и HTTP/2.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;iohk&quot;&gt;2️⃣ HTTP-сообщения&lt;/h2&gt;
  &lt;h3 id=&quot;s0TC&quot;&gt;Типы:&lt;/h3&gt;
  &lt;ol id=&quot;QkOJ&quot;&gt;
    &lt;li id=&quot;tZr4&quot;&gt;&lt;strong&gt;Запросы (Request)&lt;/strong&gt; — от клиента к серверу для получения ресурса или выполнения действия.&lt;/li&gt;
    &lt;li id=&quot;GJeJ&quot;&gt;&lt;strong&gt;Ответы (Response)&lt;/strong&gt; — от сервера клиенту, содержат результат обработки запроса.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;ngen&quot;&gt;Структура:&lt;/h3&gt;
  &lt;ol id=&quot;n9VR&quot;&gt;
    &lt;li id=&quot;4iIA&quot;&gt;&lt;strong&gt;Стартовая строка&lt;/strong&gt; — метод, URL, версия протокола.&lt;/li&gt;
    &lt;li id=&quot;avin&quot;&gt;&lt;strong&gt;HTTP-заголовки&lt;/strong&gt; — метаданные запроса/ответа.&lt;/li&gt;
    &lt;li id=&quot;dPvn&quot;&gt;&lt;strong&gt;Пустая строка&lt;/strong&gt; — разделитель метаданных и тела.&lt;/li&gt;
    &lt;li id=&quot;XhIE&quot;&gt;&lt;strong&gt;Тело сообщения (опционально)&lt;/strong&gt; — данные запроса или документа.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;CNY6&quot;&gt;3️⃣ Стартовая строка запроса&lt;/h2&gt;
  &lt;p id=&quot;DchY&quot;&gt;Состоит из:&lt;/p&gt;
  &lt;ol id=&quot;Y7n6&quot;&gt;
    &lt;li id=&quot;20I2&quot;&gt;&lt;strong&gt;Метод&lt;/strong&gt; (GET, POST, PUT, DELETE и др.)&lt;/li&gt;
    &lt;li id=&quot;kF34&quot;&gt;&lt;strong&gt;URL&lt;/strong&gt; (Scheme, Host, Port, Path, Query String)&lt;/li&gt;
    &lt;li id=&quot;iYOs&quot;&gt;&lt;strong&gt;Версия протокола&lt;/strong&gt; (HTTP/1.1, HTTP/2)&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;axBT&quot;&gt;Пример:&lt;/h3&gt;
  &lt;pre id=&quot;Jy71&quot;&gt;GET /index.html HTTP/1.1
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;xZdm&quot;&gt;4️⃣ Методы HTTP&lt;/h2&gt;
  &lt;ul id=&quot;2oXh&quot;&gt;
    &lt;li id=&quot;cvMF&quot;&gt;&lt;strong&gt;GET&lt;/strong&gt; — получить ресурс.&lt;/li&gt;
    &lt;li id=&quot;Cpfo&quot;&gt;&lt;strong&gt;POST&lt;/strong&gt; — отправить данные на сервер.&lt;/li&gt;
    &lt;li id=&quot;E2ji&quot;&gt;&lt;strong&gt;PUT&lt;/strong&gt; — обновить ресурс.&lt;/li&gt;
    &lt;li id=&quot;aVje&quot;&gt;&lt;strong&gt;DELETE&lt;/strong&gt; — удалить ресурс.&lt;/li&gt;
    &lt;li id=&quot;nLXA&quot;&gt;&lt;strong&gt;HEAD, OPTIONS, PATCH&lt;/strong&gt; — вспомогательные методы.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;NVX6&quot;&gt;&lt;strong&gt;Примечание:&lt;/strong&gt; Некоторые методы могут иметь тело запроса (POST, PUT), другие — нет (GET, DELETE).&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;gLlf&quot;&gt;5️⃣ URL-компоненты&lt;/h2&gt;
  &lt;ul id=&quot;sKwl&quot;&gt;
    &lt;li id=&quot;5wwn&quot;&gt;&lt;strong&gt;Scheme&lt;/strong&gt; — протокол (http://, https://)&lt;/li&gt;
    &lt;li id=&quot;4MTP&quot;&gt;&lt;strong&gt;Host&lt;/strong&gt; — доменное имя или IP&lt;/li&gt;
    &lt;li id=&quot;pzU8&quot;&gt;&lt;strong&gt;Port&lt;/strong&gt; — номер порта (по умолчанию для http 80, https 443)&lt;/li&gt;
    &lt;li id=&quot;cOEz&quot;&gt;&lt;strong&gt;Path&lt;/strong&gt; — путь к ресурсу (например /index.html)&lt;/li&gt;
    &lt;li id=&quot;BU3b&quot;&gt;&lt;strong&gt;Query String&lt;/strong&gt; — параметры запроса (?param=value&amp;amp;param2=value2)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;BSWB&quot;&gt;Обязательные: Scheme + Host. Остальные опциональны.&lt;/p&gt;
  &lt;p id=&quot;LYDv&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;HAii&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/63/02/6302285c-5523-473a-bbb1-99b09fdb4b05.png&quot; width=&quot;760&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;ftpr&quot;&gt;7️⃣ HTTP-заголовки&lt;/h2&gt;
  &lt;p id=&quot;g3pE&quot;&gt;&lt;strong&gt;Формат:&lt;/strong&gt; &lt;code&gt;Имя-Заголовок: Значение&lt;/code&gt;&lt;br /&gt;&lt;strong&gt;Регистрозависимость:&lt;/strong&gt; нет, но принято начинать каждое слово с заглавной буквы.&lt;/p&gt;
  &lt;h3 id=&quot;z5iG&quot;&gt;Категории:&lt;/h3&gt;
  &lt;ol id=&quot;aaA8&quot;&gt;
    &lt;li id=&quot;J951&quot;&gt;Общие — применяются ко всему сообщению.&lt;/li&gt;
    &lt;li id=&quot;UYOE&quot;&gt;Запроса — уточняют информацию о запросе.&lt;/li&gt;
    &lt;li id=&quot;CIBz&quot;&gt;Представления — указывают формат данных и кодировку, применяются с телом запроса.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;HcqL&quot;&gt;8️⃣ Тело запроса&lt;/h2&gt;
  &lt;ul id=&quot;wmmS&quot;&gt;
    &lt;li id=&quot;9trI&quot;&gt;&lt;strong&gt;Обязательное&lt;/strong&gt; только для методов, которые отправляют данные (POST, PUT).&lt;/li&gt;
    &lt;li id=&quot;imIh&quot;&gt;&lt;strong&gt;Отсутствует&lt;/strong&gt; у GET, DELETE, HEAD, OPTIONS.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;ZEY1&quot;&gt;9️⃣ HTTP-ответы&lt;/h2&gt;
  &lt;p id=&quot;gcEi&quot;&gt;&lt;strong&gt;Структура:&lt;/strong&gt; аналогична запросу — стартовая строка (status line), заголовки, тело.&lt;/p&gt;
  &lt;h3 id=&quot;wMwd&quot;&gt;Строка статуса&lt;/h3&gt;
  &lt;p id=&quot;e06I&quot;&gt;Содержит:&lt;/p&gt;
  &lt;ol id=&quot;lYzs&quot;&gt;
    &lt;li id=&quot;BK7z&quot;&gt;Версию протокола&lt;/li&gt;
    &lt;li id=&quot;DQqX&quot;&gt;Код состояния (HTTP status code)&lt;/li&gt;
    &lt;li id=&quot;Gkyg&quot;&gt;Текстовое пояснение к коду&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;fpr5&quot;&gt;Коды состояния&lt;/h3&gt;
  &lt;ul id=&quot;3tDa&quot;&gt;
    &lt;li id=&quot;JI7Q&quot;&gt;1xx — информационные&lt;/li&gt;
    &lt;li id=&quot;0Kkd&quot;&gt;2xx — успех (200 OK, 201 Created)&lt;/li&gt;
    &lt;li id=&quot;7BQy&quot;&gt;3xx — редирект&lt;/li&gt;
    &lt;li id=&quot;oTBG&quot;&gt;4xx — ошибка клиента (400 Bad Request, 404 Not Found)&lt;/li&gt;
    &lt;li id=&quot;f6JT&quot;&gt;5xx — ошибка сервера (500 Internal Server Error)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;8yZX&quot;&gt;10️⃣ Заголовки ответа&lt;/h2&gt;
  &lt;ul id=&quot;K7Pf&quot;&gt;
    &lt;li id=&quot;JZZ8&quot;&gt;&lt;strong&gt;Формат:&lt;/strong&gt; &lt;code&gt;Имя: Значение&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;12rE&quot;&gt;&lt;strong&gt;Назначение:&lt;/strong&gt; уточнение ответа, не влияет на тело.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;v0il&quot;&gt;11️⃣ Тело ответа&lt;/h2&gt;
  &lt;ul id=&quot;wi1x&quot;&gt;
    &lt;li id=&quot;K7rN&quot;&gt;Необязательное.&lt;/li&gt;
    &lt;li id=&quot;nNn6&quot;&gt;Присутствует для большинства ответов (HTML, JSON, XML).&lt;/li&gt;
    &lt;li id=&quot;ra5Q&quot;&gt;Отсутствует для 201 Created, 204 No Content.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;utlV&quot;&gt;12️⃣ Безопасность: HTTP vs HTTPS&lt;/h2&gt;
  &lt;ul id=&quot;1Qtk&quot;&gt;
    &lt;li id=&quot;uTPI&quot;&gt;HTTP — данные передаются &lt;strong&gt;в открытом виде&lt;/strong&gt;.&lt;/li&gt;
    &lt;li id=&quot;EHh9&quot;&gt;HTTPS — данные &lt;strong&gt;шифруются&lt;/strong&gt;, используется порт 443, защищает учетные данные пользователей.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;KxKA&quot;&gt;13️⃣ Практика: как отправить HTTP-запрос&lt;/h2&gt;
  &lt;h3 id=&quot;l1uY&quot;&gt;Инструменты:&lt;/h3&gt;
  &lt;ol id=&quot;Ilh0&quot;&gt;
    &lt;li id=&quot;vNiy&quot;&gt;&lt;strong&gt;Инструменты разработчика в браузере (F12 / Ctrl+Shift+I)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;JXuH&quot;&gt;
      &lt;li id=&quot;gNdC&quot;&gt;Вкладка Network показывает все запросы, метод, URL и статус.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;bdfc&quot;&gt;&lt;strong&gt;cURL&lt;/strong&gt; — командная утилита для отправки запросов:&lt;code&gt;curl -v https://selectel.ru/blog &lt;/code&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;bRMe&quot;&gt;🔹 Идемпотентность в API&lt;/h1&gt;
  &lt;h2 id=&quot;qaid&quot;&gt;1️⃣ Определение&lt;/h2&gt;
  &lt;ul id=&quot;DDEi&quot;&gt;
    &lt;li id=&quot;CSC3&quot;&gt;&lt;strong&gt;Идемпотентность&lt;/strong&gt; — повторение действия не изменяет результат после первого выполнения.&lt;/li&gt;
    &lt;li id=&quot;B3qf&quot;&gt;Позволяет избежать дублирования и непредсказуемых результатов при сетевых сбоях.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;NjeL&quot;&gt;2️⃣ Примеры&lt;/h2&gt;
  &lt;h3 id=&quot;ATPd&quot;&gt;Пицца:&lt;/h3&gt;
  &lt;pre id=&quot;H0LM&quot;&gt;orders = {}

def place_order(order_id, pizza):
    if order_id in orders:
        return &amp;quot;Заказ уже существует.&amp;quot;
    orders[order_id] = pizza
    return &amp;quot;Заказ успешно создан.&amp;quot;

first_try = place_order(&amp;quot;123&amp;quot;, &amp;quot;Пепперони&amp;quot;)
second_try = place_order(&amp;quot;123&amp;quot;, &amp;quot;Пепперони&amp;quot;)
print(first_try)  # Заказ успешно создан.
print(second_try) # Заказ уже существует.
&lt;/pre&gt;
  &lt;ul id=&quot;p5vH&quot;&gt;
    &lt;li id=&quot;zt6q&quot;&gt;Повторный запрос &lt;strong&gt;не создаёт дубликат&lt;/strong&gt; заказа.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;79gf&quot;&gt;3️⃣ Идемпотентные методы HTTP&lt;/h2&gt;
  &lt;ul id=&quot;iXD6&quot;&gt;
    &lt;li id=&quot;Ly2T&quot;&gt;&lt;strong&gt;GET&lt;/strong&gt; — получение данных&lt;/li&gt;
    &lt;li id=&quot;8bna&quot;&gt;&lt;strong&gt;PUT&lt;/strong&gt; — обновление ресурса&lt;/li&gt;
    &lt;li id=&quot;WYZZ&quot;&gt;&lt;strong&gt;DELETE&lt;/strong&gt; — удаление ресурса&lt;/li&gt;
  &lt;/ul&gt;
  &lt;blockquote id=&quot;M2Su&quot;&gt;Любой повторный запрос не изменяет состояние сервера более одного раза.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;RHm5&quot;&gt;4️⃣ Ключ идемпотентности&lt;/h2&gt;
  &lt;ul id=&quot;sp2O&quot;&gt;
    &lt;li id=&quot;l0R8&quot;&gt;Уникальный идентификатор операции (например UUID).&lt;/li&gt;
    &lt;li id=&quot;7ccn&quot;&gt;Система распознает повторные запросы и &lt;strong&gt;не выполняет их снова&lt;/strong&gt;.&lt;/li&gt;
    &lt;li id=&quot;wCg9&quot;&gt;Пример: перевод денег, где повторный запрос не создает двойной перевод.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;bYWK&quot;&gt;5️⃣ Плюсы и минусы&lt;/h2&gt;
  &lt;p id=&quot;WDPo&quot;&gt;&lt;strong&gt;Плюсы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;NEek&quot;&gt;
    &lt;li id=&quot;P9Pw&quot;&gt;Надежность и стабильность системы&lt;/li&gt;
    &lt;li id=&quot;mma1&quot;&gt;Предсказуемость действий&lt;/li&gt;
    &lt;li id=&quot;IRqR&quot;&gt;Упрощение разработки и тестирования&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;z2BY&quot;&gt;&lt;strong&gt;Минусы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;pjVE&quot;&gt;
    &lt;li id=&quot;e8mV&quot;&gt;Требует дополнительного проектирования&lt;/li&gt;
    &lt;li id=&quot;dG3L&quot;&gt;Может ограничивать некоторые сценарии бизнес-логики&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;OT1k&quot;&gt;6️⃣ Вывод&lt;/h2&gt;
  &lt;ul id=&quot;ndeT&quot;&gt;
    &lt;li id=&quot;Qygx&quot;&gt;HTTP — расширяемый протокол прикладного уровня для веба.&lt;/li&gt;
    &lt;li id=&quot;DgnL&quot;&gt;HTTPS обеспечивает безопасную передачу данных.&lt;/li&gt;
    &lt;li id=&quot;ed8Y&quot;&gt;Идемпотентность — ключ к надежности API и предотвращению дублирования действий.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;vfmN&quot;&gt;&lt;br /&gt;Еще посмотри тут: &lt;/p&gt;
  &lt;p id=&quot;JyBI&quot;&gt;&lt;a href=&quot;https://youtu.be/OyfroULbRN4?si=u1IhOAgFGL1f66G5&quot; target=&quot;_blank&quot;&gt;https://youtu.be/OyfroULbRN4?si=u1IhOAgFGL1f66G5&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;Opfw&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;dREH&quot;&gt;и почитать тут &lt;a href=&quot;https://habr.com/ru/articles/739166/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/articles/739166/&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:FXd3UL2XDBL</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/FXd3UL2XDBL?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Тестирование бэка: Swagger. Postman</title><published>2025-10-20T08:12:25.564Z</published><updated>2025-11-25T14:46:25.613Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/30/ae/30ae4f8d-0a81-471f-960e-dd8939b9e1c7.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/webt/yb/fz/_k/ybfz_ksn6uvm5mkxoljdekflodi.jpeg&quot;&gt;Что такое API?</summary><content type="html">
  &lt;p id=&quot;szlm&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/464261/&quot; target=&quot;_blank&quot;&gt;Что такое API?&lt;/a&gt;&lt;/p&gt;
  &lt;figure id=&quot;H6RE&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4c/ca/4cca692d-512a-492d-973f-6e56920aa429.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;qPm5&quot;&gt;Что такое &lt;a href=&quot;https://teletype.in/@qafeelsgood/Swagger&quot; target=&quot;_blank&quot;&gt;Swagger&lt;/a&gt;?&lt;/p&gt;
  &lt;p id=&quot;huyb&quot;&gt;&lt;a href=&quot;https://habr.com/ru/companies/kolesa/articles/351250/&quot; target=&quot;_blank&quot;&gt;Postman&lt;/a&gt;: посмотреть, &lt;a href=&quot;https://www.youtube.com/watch?v=zfrQtU8eCEo&quot; target=&quot;_blank&quot;&gt;как отправлять запросы, настраивать url, метод, заголовки и тело запроса.&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;bJWU&quot;&gt;Виды авторизации: API токен, Bearer token, basic auth&lt;/p&gt;
  &lt;p id=&quot;Z4uO&quot;&gt;Вкладка Tests/Scripts в Postman: как добавить в запрос дополнительную проверку на код ответа, на время ожидания ответа.&lt;/p&gt;
  &lt;p id=&quot;sGNy&quot;&gt;Переменные в Postman: как добавить переменную окружения и использовать в запросе.&lt;/p&gt;
  &lt;p id=&quot;Jvu9&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/&quot; target=&quot;_blank&quot;&gt;Как в целом можно тестировать бэк&lt;/a&gt;: статья от Ольги Назиной.&lt;/p&gt;
  &lt;p id=&quot;nauT&quot;&gt;Чек-лист из этой статьи перенеси себе в шпаргалку и желательно запомнить несколько пунктов оттуда&lt;/p&gt;
  &lt;p id=&quot;lSp0&quot;&gt;Тестовый API &lt;a href=&quot;https://petstore.swagger.io/&quot; target=&quot;_blank&quot;&gt;https://petstore.swagger.io/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;hl11&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;n5PE&quot;&gt;1️⃣ Что такое API 🖥️&lt;/h3&gt;
  &lt;p id=&quot;dk7P&quot;&gt;&lt;strong&gt;Описание:&lt;/strong&gt;&lt;br /&gt;API (Application Programming Interface) — это контракт, который предоставляет программа.&lt;/p&gt;
  &lt;blockquote id=&quot;ThdU&quot;&gt;«Ко мне можно обращаться так и так, я обязуюсь делать то и это».&lt;/blockquote&gt;
  &lt;p id=&quot;cQlD&quot;&gt;API включает:&lt;/p&gt;
  &lt;ul id=&quot;O6Ot&quot;&gt;
    &lt;li id=&quot;AGxZ&quot;&gt;операции, которые можно выполнить&lt;/li&gt;
    &lt;li id=&quot;Fv2H&quot;&gt;данные на входе&lt;/li&gt;
    &lt;li id=&quot;kSaS&quot;&gt;данные на выходе (результат или ошибка)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;lnLX&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;br /&gt;Если переводить на русский — это как договор на покупку машины:&lt;/p&gt;
  &lt;ul id=&quot;2qXH&quot;&gt;
    &lt;li id=&quot;3b65&quot;&gt;мои обязанности — внести сумму&lt;/li&gt;
    &lt;li id=&quot;MvIZ&quot;&gt;обязанности продавца — дать машину&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ee7c&quot;&gt;&lt;strong&gt;Функции API:&lt;/strong&gt;&lt;br /&gt;API — это набор функций, может быть одна функция или много.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;l41k&quot;&gt;2️⃣ Зачем тестировщику знать API 🔍&lt;/h3&gt;
  &lt;p id=&quot;gh6k&quot;&gt;Даже если вы тестируете GUI, API всегда есть в системе:&lt;/p&gt;
  &lt;ul id=&quot;6igm&quot;&gt;
    &lt;li id=&quot;OFKx&quot;&gt;оплата товаров и билетов через платежные системы&lt;/li&gt;
    &lt;li id=&quot;9mzh&quot;&gt;система внутри себя общается через API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;UxNy&quot;&gt;API позволяет:&lt;/p&gt;
  &lt;ul id=&quot;7NZh&quot;&gt;
    &lt;li id=&quot;BPwl&quot;&gt;проверять логику работы&lt;/li&gt;
    &lt;li id=&quot;BV63&quot;&gt;ускорять тестирование без GUI&lt;/li&gt;
    &lt;li id=&quot;tsxx&quot;&gt;локализовать баги быстрее&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Tf8o&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;br /&gt;Создание пользователя через Postman вместо ручного заполнения формы — экономит много времени.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;xzKg&quot;&gt;3️⃣ Контракт и интерфейс 📝&lt;/h3&gt;
  &lt;p id=&quot;zOz2&quot;&gt;Контракт API = интерфейс. Пользователь работает с GUI, программа — с API.&lt;/p&gt;
  &lt;p id=&quot;Xdf5&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;br /&gt;Нажимаете кнопку «загрузить отчет», система вызывает API-функции, которые собирают данные из 10 разных функций, пользователь видит готовый отчет, не зная внутренней реализации.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;3eez&quot;&gt;4️⃣ Вызовы API 🔗&lt;/h3&gt;
  &lt;p id=&quot;ro5f&quot;&gt;&lt;strong&gt;Прямые вызовы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;UBWR&quot;&gt;
    &lt;li id=&quot;LC4f&quot;&gt;Система вызывает функции внутри себя&lt;/li&gt;
    &lt;li id=&quot;S3hh&quot;&gt;Система вызывает метод другой системы&lt;/li&gt;
    &lt;li id=&quot;ZLNo&quot;&gt;Человек вызывает метод через Postman&lt;/li&gt;
    &lt;li id=&quot;7pVa&quot;&gt;Автотесты дергают методы&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;F25K&quot;&gt;&lt;strong&gt;Косвенные вызовы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;3fKE&quot;&gt;
    &lt;li id=&quot;aWta&quot;&gt;Пользователь работает через GUI, кнопки вызывают API-функции&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ybYS&quot;&gt;5️⃣ Тестирование API ✅&lt;/h3&gt;
  &lt;p id=&quot;csBu&quot;&gt;Тестирование API = проверка функциональности через API, чаще Remote API (интеграция двух систем).&lt;/p&gt;
  &lt;p id=&quot;PFDq&quot;&gt;&lt;strong&gt;Цели:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;FmDc&quot;&gt;
    &lt;li id=&quot;Lxip&quot;&gt;автотесты на уровне API&lt;/li&gt;
    &lt;li id=&quot;xOCh&quot;&gt;интеграционные проверки между системами&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;2jNB&quot;&gt;6️⃣ Инструменты для тестирования API 🛠️&lt;/h3&gt;
  &lt;ul id=&quot;vUNR&quot;&gt;
    &lt;li id=&quot;tIq7&quot;&gt;&lt;strong&gt;Postman&lt;/strong&gt; — создание, отправка, тестирование HTTP-запросов&lt;/li&gt;
    &lt;li id=&quot;5emy&quot;&gt;&lt;strong&gt;Swagger&lt;/strong&gt; — документация и тестирование API&lt;/li&gt;
    &lt;li id=&quot;k3XU&quot;&gt;&lt;strong&gt;SoapUI&lt;/strong&gt; — SOAP-сервисы&lt;/li&gt;
    &lt;li id=&quot;OgCe&quot;&gt;&lt;strong&gt;Fiddler&lt;/strong&gt; — анализ HTTP-трафика&lt;/li&gt;
    &lt;li id=&quot;PyPe&quot;&gt;&lt;strong&gt;JMeter&lt;/strong&gt; — нагрузочное тестирование&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;WDjx&quot;&gt;7️⃣ Swagger 📄&lt;/h3&gt;
  &lt;p id=&quot;keEL&quot;&gt;Swagger — инструмент для:&lt;/p&gt;
  &lt;ul id=&quot;PyaO&quot;&gt;
    &lt;li id=&quot;WfLT&quot;&gt;документирования API&lt;/li&gt;
    &lt;li id=&quot;InkC&quot;&gt;тестирования запросов&lt;/li&gt;
    &lt;li id=&quot;zbuw&quot;&gt;генерации клиентского кода&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Tp7N&quot;&gt;&lt;strong&gt;Преимущества:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;aCH3&quot;&gt;
    &lt;li id=&quot;3Syk&quot;&gt;лёгкость использования&lt;/li&gt;
    &lt;li id=&quot;r0z0&quot;&gt;автоматическая генерация документации&lt;/li&gt;
    &lt;li id=&quot;Ml31&quot;&gt;поддержка разных языков и открытых стандартов&lt;/li&gt;
    &lt;li id=&quot;BfAj&quot;&gt;тестирование и валидация API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;oeuX&quot;&gt;8️⃣ HTTP-методы 🌐&lt;/h3&gt;
  &lt;ul id=&quot;NBRD&quot;&gt;
    &lt;li id=&quot;gEZr&quot;&gt;&lt;strong&gt;POST&lt;/strong&gt; — создание объекта&lt;/li&gt;
    &lt;li id=&quot;4Hzb&quot;&gt;&lt;strong&gt;GET&lt;/strong&gt; — получение данных&lt;/li&gt;
    &lt;li id=&quot;UxiY&quot;&gt;&lt;strong&gt;PUT&lt;/strong&gt; — редактирование&lt;/li&gt;
    &lt;li id=&quot;HBMk&quot;&gt;&lt;strong&gt;DELETE&lt;/strong&gt; — удаление&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;it75&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;9iGQ&quot;&gt;POST /pets
{
  &amp;quot;name&amp;quot;: &amp;quot;doggie&amp;quot;,
  &amp;quot;status&amp;quot;: &amp;quot;available&amp;quot;
}
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;pKuB&quot;&gt;9️⃣ Postman 🧰&lt;/h3&gt;
  &lt;p id=&quot;OqS6&quot;&gt;&lt;strong&gt;Описание:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;6euU&quot;&gt;
    &lt;li id=&quot;G5j1&quot;&gt;Создание коллекций запросов&lt;/li&gt;
    &lt;li id=&quot;z4UT&quot;&gt;Тестирование API&lt;/li&gt;
    &lt;li id=&quot;TdUC&quot;&gt;Переменные и окружения&lt;/li&gt;
    &lt;li id=&quot;NQUe&quot;&gt;Collection Runner&lt;/li&gt;
    &lt;li id=&quot;IwAQ&quot;&gt;Документирование API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;brQG&quot;&gt;🔟 Скрипты и тесты в Postman 📝&lt;/h3&gt;
  &lt;p id=&quot;GP20&quot;&gt;&lt;strong&gt;Pre-request Script:&lt;/strong&gt; выполняется перед запросом&lt;br /&gt;&lt;strong&gt;Tests:&lt;/strong&gt; выполняется после запроса, проверяет ответ&lt;/p&gt;
  &lt;p id=&quot;ERub&quot;&gt;&lt;strong&gt;Пример теста:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;Rjjg&quot;&gt;pm.test(&amp;quot;Status is ok&amp;quot;, function () {
  pm.response.to.be.ok;
});
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;x013&quot;&gt;1️⃣1️⃣ Переменные ⚙️&lt;/h3&gt;
  &lt;ul id=&quot;2nCu&quot;&gt;
    &lt;li id=&quot;BKnc&quot;&gt;Глобальные&lt;/li&gt;
    &lt;li id=&quot;A6Md&quot;&gt;Окружений&lt;/li&gt;
    &lt;li id=&quot;1Q4C&quot;&gt;Коллекции&lt;/li&gt;
    &lt;li id=&quot;6Rqc&quot;&gt;Локальные&lt;/li&gt;
    &lt;li id=&quot;I8xi&quot;&gt;Уровня данных&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;O9UP&quot;&gt;Использование: &lt;code&gt;{{variable_name}}&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;m5NW&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;3UrJ&quot;&gt;pm.environment.set(&amp;quot;userId&amp;quot;, 777);
pm.environment.get(&amp;quot;userId&amp;quot;);
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;FYoK&quot;&gt;1️⃣2️⃣ Collection Runner ▶️&lt;/h3&gt;
  &lt;ul id=&quot;jwf7&quot;&gt;
    &lt;li id=&quot;OAnW&quot;&gt;Запускает все запросы коллекции или папки&lt;/li&gt;
    &lt;li id=&quot;06wM&quot;&gt;Итерации&lt;/li&gt;
    &lt;li id=&quot;70KZ&quot;&gt;Файл данных для разных тестов&lt;/li&gt;
    &lt;li id=&quot;PUAK&quot;&gt;Формирует отчет&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ssB4&quot;&gt;1️⃣3️⃣ Консоль Postman 🖥️&lt;/h3&gt;
  &lt;ul id=&quot;OTOS&quot;&gt;
    &lt;li id=&quot;lKZY&quot;&gt;Отладка скриптов&lt;/li&gt;
    &lt;li id=&quot;DVlC&quot;&gt;Лог запросов и ответов&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;45pS&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;rvHO&quot;&gt;console.log(pm.response.json());
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;NfyR&quot;&gt;1️⃣4️⃣ Практика: создание цепочки запросов 🔄&lt;/h3&gt;
  &lt;ol id=&quot;Tn7K&quot;&gt;
    &lt;li id=&quot;6RHH&quot;&gt;GET &lt;code&gt;https://postman-echo.com/get?userId=777&lt;/code&gt; → сохранить &lt;code&gt;userId&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;vUGg&quot;&gt;POST &lt;code&gt;https://postman-echo.com/post&lt;/code&gt; с телом:&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;mZmx&quot;&gt;{&amp;quot;userId&amp;quot;: {{userId}}, &amp;quot;username&amp;quot;: &amp;quot;Bob&amp;quot;}
&lt;/pre&gt;
  &lt;ol id=&quot;5RFI&quot;&gt;
    &lt;li id=&quot;IvVo&quot;&gt;Тест на совпадение &lt;code&gt;userId&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;yZO1&quot;&gt;Проверка схемы JSON через tv4&lt;/li&gt;
    &lt;li id=&quot;B08A&quot;&gt;Запуск через Collection Runner с файлом данных &lt;code&gt;users.json&lt;/code&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;zxoP&quot;&gt;1️⃣5️⃣ Полезные команды 💻&lt;/h3&gt;
  &lt;pre id=&quot;2zp3&quot;&gt;// Переменные
pm.environment.set(&amp;quot;key&amp;quot;, &amp;quot;value&amp;quot;);
pm.environment.get(&amp;quot;key&amp;quot;);

// Ассерты
pm.test(&amp;quot;value is true&amp;quot;, function() {
  pm.expect(true).to.be.true;
});

// GET-запрос
pm.sendRequest(&amp;quot;https://postman-echo.com/get&amp;quot;, (err, res) =&amp;gt; console.log(res));
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;5llr&quot;&gt;1️⃣6️⃣ Заключение 🏁&lt;/h3&gt;
  &lt;p id=&quot;g5Th&quot;&gt;&lt;strong&gt;Плюсы Postman:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;uUMb&quot;&gt;
    &lt;li id=&quot;cVQT&quot;&gt;наглядность&lt;/li&gt;
    &lt;li id=&quot;Twhk&quot;&gt;быстрый старт&lt;/li&gt;
    &lt;li id=&quot;atfS&quot;&gt;написание тестов&lt;/li&gt;
    &lt;li id=&quot;GBSh&quot;&gt;интеграция с CI через Newman&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;HOtA&quot;&gt;&lt;strong&gt;Минусы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;fAYg&quot;&gt;
    &lt;li id=&quot;IEvo&quot;&gt;редактирование коллекций только через Postman&lt;/li&gt;
    &lt;li id=&quot;zH85&quot;&gt;сложности при ревью JSON&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;BMp1&quot;&gt;Коллекции Postman — &lt;strong&gt;живая интерактивная документация&lt;/strong&gt;, ускоряющая тестирование и разработку.&lt;/p&gt;
  &lt;p id=&quot;dF63&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;h15J&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;IFQ8&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;4ghf&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/zfrQtU8eCEo?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;Awbz&quot;&gt;&lt;/h3&gt;
  &lt;figure id=&quot;f1Gq&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/8f/29/8f29e058-dc0f-4184-9150-2c7bf967d20c.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hGrf&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;Zpud&quot;&gt;1️⃣ Введение в тестирование REST API 🛠️&lt;/h2&gt;
  &lt;ul id=&quot;Y9PF&quot;&gt;
    &lt;li id=&quot;vvVQ&quot;&gt;Ручной тестировщик часто пугается API: «Что проверять, как, с чего начать?»&lt;/li&gt;
    &lt;li id=&quot;oven&quot;&gt;&lt;strong&gt;Принцип:&lt;/strong&gt; тестирование API похоже на GUI — сначала &lt;strong&gt;тест-дизайн и проверки&lt;/strong&gt;, потом технические детали (заголовки, тело, параметры).&lt;/li&gt;
    &lt;li id=&quot;8qWQ&quot;&gt;&lt;strong&gt;Чек-лист:&lt;/strong&gt; помогает систематически проверять функционал, ничего не упустить.&lt;/li&gt;
    &lt;li id=&quot;TxMu&quot;&gt;Практика будет на методе &lt;code&gt;doRegister&lt;/code&gt; системы Users.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;uVmy&quot;&gt;2️⃣ Общий чек-лист проверок ✅&lt;/h3&gt;
  &lt;p id=&quot;ENR4&quot;&gt;&lt;strong&gt;Основные категории:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;UuV3&quot;&gt;
    &lt;li id=&quot;lWgD&quot;&gt;&lt;strong&gt;Тело запроса:&lt;/strong&gt; соответствует примеру и ТЗ&lt;/li&gt;
    &lt;li id=&quot;6kRJ&quot;&gt;&lt;strong&gt;Бизнес-логика:&lt;/strong&gt; позитивные и негативные сценарии&lt;/li&gt;
    &lt;li id=&quot;Nz1t&quot;&gt;&lt;strong&gt;Параметры:&lt;/strong&gt; обязательность, корректность, работа разных значений&lt;/li&gt;
    &lt;li id=&quot;6Ea3&quot;&gt;&lt;strong&gt;Перестановка элементов:&lt;/strong&gt; заголовки, тело&lt;/li&gt;
    &lt;li id=&quot;d3lQ&quot;&gt;&lt;strong&gt;Регистрозависимость:&lt;/strong&gt; заголовки и тело&lt;/li&gt;
    &lt;li id=&quot;6N0u&quot;&gt;&lt;strong&gt;Ошибки:&lt;/strong&gt; не well formed XML / JSON&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;hlxj&quot;&gt;&lt;strong&gt;Где искать параметры:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;3tr2&quot;&gt;
    &lt;li id=&quot;IAIA&quot;&gt;URL&lt;/li&gt;
    &lt;li id=&quot;wovx&quot;&gt;Заголовки&lt;/li&gt;
    &lt;li id=&quot;VKfI&quot;&gt;Тело запроса&lt;/li&gt;
    &lt;li id=&quot;JAuf&quot;&gt;Комбинации&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;05FR&quot;&gt;3️⃣ Тестирование параметров 🧩&lt;/h3&gt;
  &lt;p id=&quot;XUNB&quot;&gt;&lt;strong&gt;Проверки для каждого параметра:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;Urz3&quot;&gt;
    &lt;li id=&quot;u2fj&quot;&gt;Корректный параметр (по примеру или документации)&lt;/li&gt;
    &lt;li id=&quot;VrqN&quot;&gt;Обязательность (что если параметр не передан?)&lt;/li&gt;
    &lt;li id=&quot;bUAO&quot;&gt;Бизнес-логика (например, проверка валидных/невалидных комбинаций)&lt;/li&gt;
    &lt;li id=&quot;4Mke&quot;&gt;Регистрозависимость (для текстовых параметров)&lt;/li&gt;
    &lt;li id=&quot;izB8&quot;&gt;Перестановка параметров (влияет ли порядок на работу метода)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;KwZl&quot;&gt;&lt;strong&gt;Принцип:&lt;/strong&gt; тестируем параметры REST так же, как GUI-поля формы.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;Ku0Z&quot;&gt;4️⃣ Тестирование заголовков 📬&lt;/h3&gt;
  &lt;ul id=&quot;iXNc&quot;&gt;
    &lt;li id=&quot;5uPm&quot;&gt;Заголовки из документации должны работать&lt;/li&gt;
    &lt;li id=&quot;jmgq&quot;&gt;Проверка &lt;strong&gt;обязательности заголовка&lt;/strong&gt; (что если не передан)&lt;/li&gt;
    &lt;li id=&quot;8QpI&quot;&gt;Проверка &lt;strong&gt;неправильных значений&lt;/strong&gt; (текст ошибки)&lt;/li&gt;
    &lt;li id=&quot;M7Y0&quot;&gt;Позитивные тесты по документации&lt;/li&gt;
    &lt;li id=&quot;xISm&quot;&gt;Регистронезависимость заголовков&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ZkpL&quot;&gt;5️⃣ Проверка ответа API 📡&lt;/h3&gt;
  &lt;p id=&quot;Oobx&quot;&gt;&lt;strong&gt;Основное, что проверяем:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;JA9b&quot;&gt;
    &lt;li id=&quot;ASpE&quot;&gt;&lt;strong&gt;Status Code:&lt;/strong&gt; соответствует документации&lt;/li&gt;
    &lt;li id=&quot;TLtu&quot;&gt;&lt;strong&gt;Body:&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;p9Rw&quot;&gt;
      &lt;li id=&quot;0cyd&quot;&gt;Все поля ответа&lt;/li&gt;
      &lt;li id=&quot;uqge&quot;&gt;Значения в полях&lt;/li&gt;
      &lt;li id=&quot;ftx6&quot;&gt;Сообщения об ошибках&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;GVNf&quot;&gt;&lt;strong&gt;Сравнения:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;OVSv&quot;&gt;
    &lt;li id=&quot;YZXM&quot;&gt;Поля с ТЗ&lt;/li&gt;
    &lt;li id=&quot;Sjm9&quot;&gt;Поля между SOAP и REST&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;49rc&quot;&gt;6️⃣ Позитивное vs негативное тестирование 🌈⚠️&lt;/h3&gt;
  &lt;ul id=&quot;bg55&quot;&gt;
    &lt;li id=&quot;dcJy&quot;&gt;Начинаем с &lt;strong&gt;позитивного&lt;/strong&gt; теста: работает система при нормальных данных&lt;/li&gt;
    &lt;li id=&quot;6Emm&quot;&gt;Негативное тестирование иногда важнее (интеграция с внешними системами)&lt;/li&gt;
    &lt;ul id=&quot;ZKPP&quot;&gt;
      &lt;li id=&quot;1pR7&quot;&gt;Проверяем, чтобы сообщения об ошибках были понятны пользователю&lt;/li&gt;
      &lt;li id=&quot;9S1y&quot;&gt;Сокращаем обращения в техподдержку&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;RjK7&quot;&gt;7️⃣ Порядок тестирования ⏱️&lt;/h3&gt;
  &lt;ol id=&quot;BEXw&quot;&gt;
    &lt;li id=&quot;yQo7&quot;&gt;Примеры из ТЗ → проверяем, что метод работает&lt;/li&gt;
    &lt;li id=&quot;BBcd&quot;&gt;Основной позитивный сценарий → проверяем рабочую цепочку&lt;/li&gt;
    &lt;li id=&quot;5THD&quot;&gt;Альтернативные сценарии → дополнительные условия&lt;/li&gt;
    &lt;li id=&quot;Rmpt&quot;&gt;Негативные сценарии → проверка ошибок и нестандартных данных&lt;/li&gt;
    &lt;li id=&quot;ERVs&quot;&gt;Проверка параметров, заголовков, тела, URL и типа метода&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;YVFM&quot;&gt;8️⃣ Практика: Users — doRegister 👩‍💻&lt;/h3&gt;
  &lt;p id=&quot;KWnN&quot;&gt;&lt;strong&gt;Пример запроса:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;G0Bm&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;milli@mail.ru&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;ul id=&quot;BZJM&quot;&gt;
    &lt;li id=&quot;JPDl&quot;&gt;Тип запроса: POST&lt;/li&gt;
    &lt;li id=&quot;B4yq&quot;&gt;URL: &lt;code&gt;http://users.bugred.ru/tasks/rest/doregister&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;S6ig&quot;&gt;Если пример не уникален → редактируем данные&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;WsxV&quot;&gt;&lt;strong&gt;С Postman (динамический email и имя):&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;5Syf&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;milli{{$randomInt}}@mail.ru&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька{{$randomInt}}&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ePhN&quot;&gt;9️⃣ Проверка основного позитивного сценария 🎯&lt;/h3&gt;
  &lt;ul id=&quot;WlU0&quot;&gt;
    &lt;li id=&quot;i5ZN&quot;&gt;Проверяем, что пользователь реально создан: GUI → поиск пользователя&lt;/li&gt;
    &lt;li id=&quot;pvIL&quot;&gt;Проверяем поля: email, автор, дата изменения&lt;/li&gt;
    &lt;li id=&quot;U9Ks&quot;&gt;Проверяем авторизацию: данные работают → регистрация успешна&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;gzDI&quot;&gt;🔟 Альтернативные сценарии 🔄&lt;/h3&gt;
  &lt;ul id=&quot;icwC&quot;&gt;
    &lt;li id=&quot;NfZt&quot;&gt;Дополнительные условия из ТЗ:&lt;/li&gt;
    &lt;ul id=&quot;EOnJ&quot;&gt;
      &lt;li id=&quot;u68H&quot;&gt;Автор через REST или SOAP&lt;/li&gt;
      &lt;li id=&quot;M5A4&quot;&gt;Изменение полей возможно только через соответствующий метод&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;s70M&quot;&gt;Проверяем GUI и SOAP UI, чтобы убедиться, что ограничения соблюдаются&lt;/li&gt;
    &lt;li id=&quot;tCQ5&quot;&gt;Маленькие баги: например, регистр автора не совпадает с ТЗ → фиксируем или обновляем документацию&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;tItw&quot;&gt;1️⃣1️⃣ Негативные сценарии ❌&lt;/h3&gt;
  &lt;ul id=&quot;HI6I&quot;&gt;
    &lt;li id=&quot;RFna&quot;&gt;Проверка сообщений об ошибках&lt;/li&gt;
    &lt;li id=&quot;hZJa&quot;&gt;Сначала &lt;strong&gt;бизнес-логика&lt;/strong&gt;, потом API (well-formed JSON/XML)&lt;/li&gt;
    &lt;li id=&quot;8Muw&quot;&gt;Примеры проверки уникальности:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;ol id=&quot;G3Pk&quot;&gt;
    &lt;li id=&quot;9TB7&quot;&gt;Дубликат имени, уникальный email&lt;/li&gt;
    &lt;li id=&quot;744S&quot;&gt;Дубликат email, уникальное имя&lt;/li&gt;
    &lt;li id=&quot;0L5r&quot;&gt;Дубликаты сразу email + имя&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;ktfC&quot;&gt;&lt;strong&gt;Цель:&lt;/strong&gt; понять, что ошибка понятна, статус-код корректный&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;hr6j&quot;&gt;1️⃣2️⃣ Параметры запроса ✍️&lt;/h3&gt;
  &lt;ul id=&quot;0CWm&quot;&gt;
    &lt;li id=&quot;wuDY&quot;&gt;Проверка обязательности&lt;/li&gt;
    &lt;li id=&quot;y5YB&quot;&gt;Перестановка элементов&lt;/li&gt;
    &lt;li id=&quot;NQrp&quot;&gt;Бизнес-логика: если параметры изменены, система корректно реагирует&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;gcqA&quot;&gt;&lt;strong&gt;Принцип:&lt;/strong&gt; тестируем REST-поля так же, как GUI-поля формы&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;EayV&quot;&gt;1️⃣3️⃣ Email: тестовые проверки 📧&lt;/h3&gt;
  &lt;ul id=&quot;a7um&quot;&gt;
    &lt;li id=&quot;KheA&quot;&gt;Корректный email → позитивный тест&lt;/li&gt;
    &lt;li id=&quot;izev&quot;&gt;Верхний регистр, цифры → &lt;a href=&quot;true&quot;&gt;TEST77@mail9.ru&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;BK04&quot;&gt;С дефисами, подчеркиваниями, точками&lt;/li&gt;
    &lt;li id=&quot;G2W2&quot;&gt;Некорректные:&lt;/li&gt;
    &lt;ul id=&quot;CBEO&quot;&gt;
      &lt;li id=&quot;vYKy&quot;&gt;без точек в домене&lt;/li&gt;
      &lt;li id=&quot;cat3&quot;&gt;превышение длины (&amp;gt;320 символов)&lt;/li&gt;
      &lt;li id=&quot;vooH&quot;&gt;отсутствие @&lt;/li&gt;
      &lt;li id=&quot;Ue4s&quot;&gt;пробелы в имени и домене&lt;/li&gt;
      &lt;li id=&quot;ynxE&quot;&gt;пустое имя пользователя или домена&lt;/li&gt;
      &lt;li id=&quot;apQQ&quot;&gt;некорректный TLD&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ZOqj&quot;&gt;1️⃣4️⃣ Name: тестовые проверки 🏷️&lt;/h3&gt;
  &lt;ul id=&quot;dOTJ&quot;&gt;
    &lt;li id=&quot;hZgI&quot;&gt;Простая строка&lt;/li&gt;
    &lt;li id=&quot;7MNV&quot;&gt;Разный регистр, спецсимволы&lt;/li&gt;
    &lt;li id=&quot;z2kQ&quot;&gt;Максимальная длина: 1 000 / 1 000 000 символов&lt;/li&gt;
    &lt;li id=&quot;PEBg&quot;&gt;Проверка отображения в GUI после запроса&lt;/li&gt;
    &lt;li id=&quot;Dh3y&quot;&gt;Проверяем позитивные сценарии&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;udJu&quot;&gt;1️⃣5️⃣ Password: тестовые проверки 🔑&lt;/h3&gt;
  &lt;ul id=&quot;2ZoY&quot;&gt;
    &lt;li id=&quot;Smuw&quot;&gt;Простой пароль → позитивный тест&lt;/li&gt;
    &lt;li id=&quot;hFxZ&quot;&gt;Разные регистры, спецсимволы&lt;/li&gt;
    &lt;li id=&quot;C30Z&quot;&gt;Длинные значения → проверяем верхние границы&lt;/li&gt;
    &lt;li id=&quot;zJVB&quot;&gt;Проверка отображения и функциональности GUI&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;YKL8&quot;&gt;1️⃣6️⃣ Остальные тесты 🧪&lt;/h3&gt;
  &lt;ul id=&quot;zAbD&quot;&gt;
    &lt;li id=&quot;FscE&quot;&gt;Перестановка мест слагаемых (тело, заголовки)&lt;/li&gt;
    &lt;li id=&quot;SRUg&quot;&gt;Регистрозависимость&lt;/li&gt;
    &lt;li id=&quot;YvrR&quot;&gt;Проверка well-formed XML/JSON&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;TtD5&quot;&gt;&lt;strong&gt;Принцип:&lt;/strong&gt; API-тестирование проверяет все особенности работы метода, а GUI помогает визуально убедиться, что данные корректно обработаны.&lt;/p&gt;
  &lt;p id=&quot;S4KM&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;3DYj&quot;&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;FGwx&quot;&gt;1️⃣ Тестирование заголовков (Headers) 📬&lt;/h2&gt;
  &lt;h3 id=&quot;8JIi&quot;&gt;1.1 Основная идея&lt;/h3&gt;
  &lt;ul id=&quot;tT4g&quot;&gt;
    &lt;li id=&quot;uA3S&quot;&gt;Заголовки должны &lt;strong&gt;обрабатываться&lt;/strong&gt; либо на сервере, либо на клиенте.&lt;/li&gt;
    &lt;li id=&quot;0NIr&quot;&gt;Если заголовок никем не обрабатывается → &lt;strong&gt;лишний трафик&lt;/strong&gt;, который не нужен.&lt;/li&gt;
    &lt;li id=&quot;HVUa&quot;&gt;Принцип: &lt;strong&gt;меньшее зло&lt;/strong&gt; — либо заголовок используется, либо не нужен.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;S8Zt&quot;&gt;1.2 Поведение при отсутствии заголовка&lt;/h3&gt;
  &lt;ul id=&quot;JRM4&quot;&gt;
    &lt;li id=&quot;LkxB&quot;&gt;Используется дефолтное значение (в коде разработчика)&lt;/li&gt;
    &lt;li id=&quot;kWQv&quot;&gt;Заголовок не нужен (например, Postman может сам подставлять hidden-headers)&lt;/li&gt;
    &lt;li id=&quot;N1h3&quot;&gt;Язык (&lt;code&gt;Accept-Language&lt;/code&gt;) важен, иначе сервер может вернуть данные не на том языке&lt;/li&gt;
  &lt;/ul&gt;
  &lt;blockquote id=&quot;ENjS&quot;&gt;⚠️ Пример: если разработчик зашил русский язык по умолчанию, даже &lt;code&gt;Accept-Language: en-US&lt;/code&gt;может вернуть русский.&lt;/blockquote&gt;
  &lt;h3 id=&quot;Wk20&quot;&gt;1.3 Возможные сценарии&lt;/h3&gt;
  &lt;ul id=&quot;x22W&quot;&gt;
    &lt;li id=&quot;kN1q&quot;&gt;Заголовок не передан:&lt;/li&gt;
    &lt;ul id=&quot;wH7U&quot;&gt;
      &lt;li id=&quot;Bwgt&quot;&gt;выдаёт ошибку → понятно ли пользователю, что делать&lt;/li&gt;
      &lt;li id=&quot;zeEL&quot;&gt;применяет поведение по умолчанию&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;6oW2&quot;&gt;Заголовок передан:&lt;/li&gt;
    &lt;ul id=&quot;oQNq&quot;&gt;
      &lt;li id=&quot;8JY9&quot;&gt;верное значение → OK&lt;/li&gt;
      &lt;li id=&quot;fLWI&quot;&gt;неверное значение → сообщение об ошибке&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;YBkP&quot;&gt;1.4 Регистронезависимость&lt;/h3&gt;
  &lt;ul id=&quot;0SJm&quot;&gt;
    &lt;li id=&quot;fQ5i&quot;&gt;Заголовки должны быть &lt;strong&gt;регистронезависимы&lt;/strong&gt; по спецификации&lt;/li&gt;
    &lt;li id=&quot;tvQI&quot;&gt;Примеры:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;jYrJ&quot;&gt;Accept: application/json
Accept: APPLICATION/JSON
ACCEPT: application/json
ACCEPT: APPLICATION/JSON
ACcePT: APPlicATIon/JSon
&lt;/pre&gt;
  &lt;ul id=&quot;WvkQ&quot;&gt;
    &lt;li id=&quot;uYNW&quot;&gt;⚠️ Проверка нужна, т.к. разработчик должен прописать это в коде.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;Slxa&quot;&gt;1.5 Подводные камни&lt;/h3&gt;
  &lt;ul id=&quot;gTTZ&quot;&gt;
    &lt;li id=&quot;nDHH&quot;&gt;Прокси (например, Nginx) может менять регистр заголовков → система должна корректно обрабатывать&lt;/li&gt;
    &lt;li id=&quot;5MtT&quot;&gt;Hidden-headers в Postman → не тестируем, отправляем запрос чистым curl&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;maJD&quot;&gt;1.6 Практика (Users API)&lt;/h3&gt;
  &lt;ul id=&quot;f2bQ&quot;&gt;
    &lt;li id=&quot;a4sQ&quot;&gt;Если удалить все заголовки → &lt;code&gt;doRegister&lt;/code&gt; работает&lt;/li&gt;
    &lt;li id=&quot;PMdI&quot;&gt;Проверяем без hidden-заголовков&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;1Wb2&quot;&gt;2️⃣ Тестирование тела запроса (Body) 📝&lt;/h2&gt;
  &lt;h3 id=&quot;2lsH&quot;&gt;2.1 Основные проверки&lt;/h3&gt;
  &lt;ol id=&quot;DX5G&quot;&gt;
    &lt;li id=&quot;GiKi&quot;&gt;Правильное тело (по примеру ТЗ)&lt;/li&gt;
    &lt;li id=&quot;vvG2&quot;&gt;Различные параметры:&lt;/li&gt;
    &lt;ul id=&quot;kfSd&quot;&gt;
      &lt;li id=&quot;AqNS&quot;&gt;обязательность&lt;/li&gt;
      &lt;li id=&quot;rJn8&quot;&gt;работа параметров&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;fzqF&quot;&gt;Бизнес-логика&lt;/li&gt;
    &lt;li id=&quot;Csie&quot;&gt;Ошибки в бизнес-логике&lt;/li&gt;
    &lt;li id=&quot;Kcm5&quot;&gt;Перестановка мест слагаемых&lt;/li&gt;
    &lt;li id=&quot;dWaE&quot;&gt;Регистрозависимость&lt;/li&gt;
    &lt;li id=&quot;qxbm&quot;&gt;Ошибки: &lt;strong&gt;не well formed JSON / XML&lt;/strong&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;Pblj&quot;&gt;2.2 Перестановка мест слагаемых 🔀&lt;/h3&gt;
  &lt;ul id=&quot;eDU1&quot;&gt;
    &lt;li id=&quot;1g7L&quot;&gt;API передает пары «ключ:значение», порядок не должен влиять&lt;/li&gt;
    &lt;li id=&quot;0HmH&quot;&gt;Проверяем, что система читает по названию ключа&lt;/li&gt;
    &lt;li id=&quot;3jS0&quot;&gt;В GUI переставить поля нельзя → только в API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;cYJX&quot;&gt;&lt;strong&gt;Пример JSON:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;IXeW&quot;&gt;{
    &amp;quot;name&amp;quot;: &amp;quot;Машенька{{$randomInt}}&amp;quot;,
    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,
    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;ul id=&quot;G80G&quot;&gt;
    &lt;li id=&quot;dS58&quot;&gt;Переставляем поля → должно работать одинаково&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;TkLv&quot;&gt;2.3 Регистрозависимость 🔠&lt;/h3&gt;
  &lt;ul id=&quot;a9Hy&quot;&gt;
    &lt;li id=&quot;mUA1&quot;&gt;Названия ключей чувствительны к регистру (например, &lt;code&gt;NAME&lt;/code&gt; вместо &lt;code&gt;name&lt;/code&gt; → ошибка)&lt;/li&gt;
    &lt;li id=&quot;ujzZ&quot;&gt;В Users: регистрозависимость есть → критично для тестирования&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;pCpy&quot;&gt;2.4 Well formed JSON ✅❌&lt;/h3&gt;
  &lt;p id=&quot;X2C9&quot;&gt;&lt;strong&gt;Правила:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;c0V9&quot;&gt;
    &lt;li id=&quot;YZJm&quot;&gt;Пары «ключ:значение»&lt;/li&gt;
    &lt;li id=&quot;zkKG&quot;&gt;Данные разделены запятыми&lt;/li&gt;
    &lt;li id=&quot;ZkPi&quot;&gt;Объект в &lt;code&gt;{}&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;IVeM&quot;&gt;Массив в &lt;code&gt;[]&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;fKs7&quot;&gt;&lt;strong&gt;Ошибки:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;zAHO&quot;&gt;
    &lt;li id=&quot;g8NU&quot;&gt;Лишняя запятая после последней пары&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;iwn7&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;test@mail.com&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;,
}
&lt;/pre&gt;
  &lt;ol id=&quot;k4ET&quot;&gt;
    &lt;li id=&quot;JK1J&quot;&gt;Не пары ключ:значение&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;D172&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;test@mail.com&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька&amp;quot;,
  &amp;quot;password&amp;quot;
}
&lt;/pre&gt;
  &lt;ol id=&quot;w8wk&quot;&gt;
    &lt;li id=&quot;ButD&quot;&gt;Данные без запятых&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;bLLn&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;test@mail.com&amp;quot;
  &amp;quot;name&amp;quot;: &amp;quot;Машенька&amp;quot;
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;ol id=&quot;iSfe&quot;&gt;
    &lt;li id=&quot;aR1y&quot;&gt;Объект в квадратных скобках&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;2ItQ&quot;&gt;[
  &amp;quot;email&amp;quot;: &amp;quot;test@mail.com&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
]
&lt;/pre&gt;
  &lt;ul id=&quot;ysHI&quot;&gt;
    &lt;li id=&quot;LiZ5&quot;&gt;Ожидаемый результат: &lt;code&gt;400 Bad Request&lt;/code&gt; + сообщение &lt;code&gt;&amp;quot;Не well formed JSON&amp;quot;&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;JUzq&quot;&gt;3️⃣ Тестирование параметров в URL 🌐&lt;/h2&gt;
  &lt;h3 id=&quot;ahZA&quot;&gt;3.1 Общие принципы&lt;/h3&gt;
  &lt;ul id=&quot;9T6D&quot;&gt;
    &lt;li id=&quot;NCxV&quot;&gt;GET-параметры тестируем как body&lt;/li&gt;
    &lt;li id=&quot;SUjM&quot;&gt;Проверяем:&lt;/li&gt;
    &lt;ul id=&quot;3Uqc&quot;&gt;
      &lt;li id=&quot;ohU6&quot;&gt;корректное значение&lt;/li&gt;
      &lt;li id=&quot;nRMZ&quot;&gt;обязательность&lt;/li&gt;
      &lt;li id=&quot;EZD3&quot;&gt;бизнес-логику&lt;/li&gt;
      &lt;li id=&quot;AR3d&quot;&gt;регистрозависимость (для текстовых параметров)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;oU9f&quot;&gt;3.2 Практика (Jira Cloud API)&lt;/h3&gt;
  &lt;ul id=&quot;25nd&quot;&gt;
    &lt;li id=&quot;ZFWz&quot;&gt;Метод: &lt;code&gt;GET /rest/api/3/issue/{issueIdOrKey}&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;v8mP&quot;&gt;Параметры: id или key (&lt;code&gt;13005&lt;/code&gt; / &lt;code&gt;TEST-1&lt;/code&gt;)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;banq&quot;&gt;&lt;strong&gt;Тесты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;dCiS&quot;&gt;
    &lt;li id=&quot;04cV&quot;&gt;Правильное значение → базовый позитивный тест&lt;/li&gt;
    &lt;li id=&quot;gKm3&quot;&gt;Не передан параметр → проверка обязательности&lt;/li&gt;
    &lt;li id=&quot;4jfA&quot;&gt;Разные состояния объекта:&lt;/li&gt;
    &lt;ul id=&quot;rre4&quot;&gt;
      &lt;li id=&quot;EhZO&quot;&gt;свежесозданная&lt;/li&gt;
      &lt;li id=&quot;JBzt&quot;&gt;несколько раз изменённая&lt;/li&gt;
      &lt;li id=&quot;fzg4&quot;&gt;минимально / максимально заполненная&lt;/li&gt;
      &lt;li id=&quot;WdZo&quot;&gt;закрытая / удалённая / несуществующая&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;sfix&quot;&gt;Регистрозависимость ключа (для issue key):&lt;/li&gt;
  &lt;/ol&gt;
  &lt;pre id=&quot;d9Mb&quot;&gt;/rest/api/3/issue/test-1
/rest/api/3/issue/TEst-1
&lt;/pre&gt;
  &lt;ul id=&quot;5x73&quot;&gt;
    &lt;li id=&quot;meTr&quot;&gt;Цифры регистронезависимы, буквы — тестируем&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;n25X&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;V3q8&quot;&gt;1️⃣ Тип метода (HTTP Method) ⚡&lt;/h2&gt;
  &lt;h3 id=&quot;OzrC&quot;&gt;1.1 Основная идея&lt;/h3&gt;
  &lt;ul id=&quot;rfWC&quot;&gt;
    &lt;li id=&quot;FaGE&quot;&gt;Проверяем, как система реагирует на &lt;strong&gt;“подмену” метода&lt;/strong&gt;:&lt;/li&gt;
    &lt;ul id=&quot;OLHJ&quot;&gt;
      &lt;li id=&quot;lHeQ&quot;&gt;POST → GET (совсем разные)&lt;/li&gt;
      &lt;li id=&quot;zTFV&quot;&gt;POST → PUT (похожие)&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;9Mgp&quot;&gt;Возможные реакции:&lt;/li&gt;
    &lt;ul id=&quot;SYjB&quot;&gt;
      &lt;li id=&quot;esTc&quot;&gt;Система отрабатывает как будто всё нормально&lt;/li&gt;
      &lt;li id=&quot;wOP4&quot;&gt;Выдаёт &lt;strong&gt;понятную ошибку&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;blockquote id=&quot;LCL1&quot;&gt;⚠️ Хорошая практика — ловить “неправильные” методы сразу, особенно при интеграции, чтобы потом обновления релиза не тормозились.&lt;/blockquote&gt;
  &lt;h3 id=&quot;N7Q7&quot;&gt;1.2 Практика (Users API)&lt;/h3&gt;
  &lt;ul id=&quot;zOp3&quot;&gt;
    &lt;li id=&quot;pHWn&quot;&gt;POST → GET → &lt;strong&gt;успешно&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;vCUV&quot;&gt;POST → PUT → проверить корректность ответа&lt;/li&gt;
    &lt;li id=&quot;e5yJ&quot;&gt;Вывод: иногда API “терпимо” к методу, но это нужно фиксировать для надёжности.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;cT9O&quot;&gt;2️⃣ Тело ответа (Response Body) 📦&lt;/h2&gt;
  &lt;h3 id=&quot;tWgz&quot;&gt;2.1 Чек-лист проверки&lt;/h3&gt;
  &lt;ul id=&quot;lvO9&quot;&gt;
    &lt;li id=&quot;iPTe&quot;&gt;&lt;strong&gt;Поля&lt;/strong&gt;: какие вернулись, сравнить с ТЗ&lt;/li&gt;
    &lt;li id=&quot;XaPL&quot;&gt;&lt;strong&gt;Значения&lt;/strong&gt;: соответствие ожидаемым&lt;/li&gt;
    &lt;li id=&quot;yllz&quot;&gt;&lt;strong&gt;Текст ошибок&lt;/strong&gt;: читаемость, информативность&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;z4BD&quot;&gt;2.2 Сравнение SOAP и REST&lt;/h3&gt;
  &lt;ul id=&quot;7kpX&quot;&gt;
    &lt;li id=&quot;gd45&quot;&gt;Если есть оба интерфейса, проверить идентичность:&lt;/li&gt;
    &lt;ul id=&quot;bx5h&quot;&gt;
      &lt;li id=&quot;oGca&quot;&gt;Пустые поля могут различаться (SOAP возвращает все, REST — только заполненные)&lt;/li&gt;
      &lt;li id=&quot;3wcd&quot;&gt;SOAP использует WSDL для обязательных полей&lt;/li&gt;
      &lt;li id=&quot;hJzI&quot;&gt;REST может придерживаться “минимальных чернил”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;zYyW&quot;&gt;2.3 Особенности проверки&lt;/h3&gt;
  &lt;ul id=&quot;vFDc&quot;&gt;
    &lt;li id=&quot;CuyE&quot;&gt;Отсутствие данных на входе (поле не пришло / пустое)&lt;/li&gt;
    &lt;li id=&quot;oDyS&quot;&gt;Пустые поля на выходе → проверяем, соответствует ли документации&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;S7XZ&quot;&gt;2.4 Практика (Users API)&lt;/h3&gt;
  &lt;ul id=&quot;1C34&quot;&gt;
    &lt;li id=&quot;ho8M&quot;&gt;Базовый запрос → REST и SOAP&lt;/li&gt;
    &lt;li id=&quot;9G1T&quot;&gt;Различие: SOAP возвращает все поля, REST — только основные&lt;/li&gt;
    &lt;li id=&quot;jqde&quot;&gt;Проверяем бизнес-логику один раз → API-проверка идентична&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;wB4O&quot;&gt;3️⃣ Перестановка полей и регистрозависимость 🔀🔠&lt;/h2&gt;
  &lt;h3 id=&quot;l28o&quot;&gt;3.1 Перестановка мест слагаемых&lt;/h3&gt;
  &lt;ul id=&quot;riW4&quot;&gt;
    &lt;li id=&quot;rfMi&quot;&gt;В REST: порядок ключей не должен влиять → проверка “ключ:значение”&lt;/li&gt;
    &lt;li id=&quot;y3jj&quot;&gt;В SOAP: проверка на &lt;strong&gt;порядковые номера тегов&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;ZsQD&quot;&gt;
      &lt;li id=&quot;nK85&quot;&gt;Пример: &lt;code&gt;name&lt;/code&gt; и &lt;code&gt;email&lt;/code&gt; поменяли → SOAP выдал некорректный email → баг&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;0uP7&quot;&gt;3.2 Регистрозависимость тегов (XML)&lt;/h3&gt;
  &lt;ul id=&quot;DT5O&quot;&gt;
    &lt;li id=&quot;yb5u&quot;&gt;Открывающий и закрывающий теги должны совпадать по регистру&lt;/li&gt;
    &lt;li id=&quot;s5os&quot;&gt;Пример:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;rjE2&quot;&gt;&amp;lt;EMAIL&amp;gt;ggg55555@mail.com&amp;lt;/EMAIL&amp;gt;  → работает
&amp;lt;EMAIL&amp;gt;ggg55555@mail.com&amp;lt;/email&amp;gt;  → Bad Request
&lt;/pre&gt;
  &lt;h3 id=&quot;xQbx&quot;&gt;3.3 Well-formed XML&lt;/h3&gt;
  &lt;ul id=&quot;1b79&quot;&gt;
    &lt;li id=&quot;iFvp&quot;&gt;Пример ошибки:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;NXUt&quot;&gt;&amp;lt;wrap:doRegister&amp;gt;
  &amp;lt;email&amp;gt;ggg5555@mail.com&amp;lt;/email
  &amp;lt;name&amp;gt;Имечко 666&amp;lt;/name&amp;gt;
  &amp;lt;password&amp;gt;1&amp;lt;/password&amp;gt;
&amp;lt;/wrap:doRegister&amp;gt;
&lt;/pre&gt;
  &lt;ul id=&quot;5BBK&quot;&gt;
    &lt;li id=&quot;Ihg4&quot;&gt;Ответ: &lt;code&gt;&amp;lt;faultcode&amp;gt;SOAP-ENV:Client&amp;lt;/faultcode&amp;gt;&amp;lt;faultstring&amp;gt;Bad Request&amp;lt;/faultstring&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;Uscq&quot;&gt;🔹 Идея: проверяем адекватность ошибки при некорректной структуре&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;f85T&quot;&gt;4️⃣ Статус-коды HTTP 🟢🔴&lt;/h2&gt;
  &lt;h3 id=&quot;2hl8&quot;&gt;4.1 Основная схема&lt;/h3&gt;
  &lt;ul id=&quot;rOwt&quot;&gt;
    &lt;li id=&quot;a5oq&quot;&gt;2xx → успех&lt;/li&gt;
    &lt;li id=&quot;IEpe&quot;&gt;4xx → ошибка клиента&lt;/li&gt;
    &lt;li id=&quot;R2D2&quot;&gt;5xx → ошибка сервера&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;oF7a&quot;&gt;4.2 Возможные “нестандартные” коды&lt;/h3&gt;
  &lt;ul id=&quot;dTLS&quot;&gt;
    &lt;li id=&quot;z25L&quot;&gt;Например:&lt;/li&gt;
    &lt;ul id=&quot;WupE&quot;&gt;
      &lt;li id=&quot;nac1&quot;&gt;570 — пустой ответ на поиск&lt;/li&gt;
      &lt;li id=&quot;IMro&quot;&gt;571 — найден один ФЛ&lt;/li&gt;
      &lt;li id=&quot;bflJ&quot;&gt;572 — несколько ИП&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;4Al1&quot;&gt;Разработчик может даже перекрывать стандартные:&lt;/li&gt;
    &lt;ul id=&quot;JF1c&quot;&gt;
      &lt;li id=&quot;CL2F&quot;&gt;400 → Internal Server Error&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;bIv5&quot;&gt;⚠️ Проверяем статус-код всегда:&lt;/li&gt;
    &lt;ul id=&quot;bpKa&quot;&gt;
      &lt;li id=&quot;EEiM&quot;&gt;Хороший запрос → 200&lt;/li&gt;
      &lt;li id=&quot;YRJu&quot;&gt;Плохой запрос → 4xx/5xx (не 200!)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;ZV51&quot;&gt;4.3 Практика (Users API)&lt;/h3&gt;
  &lt;ul id=&quot;99uY&quot;&gt;
    &lt;li id=&quot;V8Wz&quot;&gt;Хороший запрос → 200 OK&lt;/li&gt;
    &lt;li id=&quot;2XWT&quot;&gt;Плохой запрос → 200 с ошибкой в теле → баг&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;lvT9&quot;&gt;🔹 Итоговый чек-лист проверки &lt;code&gt;doRegister&lt;/code&gt;&lt;/h1&gt;
  &lt;blockquote id=&quot;g3pH&quot;&gt;В первую очередь проверяем &lt;strong&gt;бизнес-логику&lt;/strong&gt;, затем API-аспекты: регистрозависимость, перестановку параметров, корректность JSON/XML, тип метода.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;FZh9&quot;&gt;1️⃣ Базовый тест (Пример из ТЗ)&lt;/h2&gt;
  &lt;p id=&quot;drMI&quot;&gt;&lt;strong&gt;Тело запроса:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;TFjx&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;milli{{$randomInt}}@mail.ru&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Машенька{{$randomInt}}&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;p id=&quot;g66j&quot;&gt;&lt;strong&gt;Ожидаемый результат:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;vozg&quot;&gt;
    &lt;li id=&quot;4TzA&quot;&gt;&lt;strong&gt;Статус:&lt;/strong&gt; 200 OK&lt;/li&gt;
    &lt;li id=&quot;osPw&quot;&gt;&lt;strong&gt;Поля ответа:&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;7UNl&quot;&gt;
      &lt;li id=&quot;yTji&quot;&gt;&lt;code&gt;name&lt;/code&gt;: отправленное имя&lt;/li&gt;
      &lt;li id=&quot;5HNK&quot;&gt;&lt;code&gt;avatar&lt;/code&gt;: стандартная аватарка&lt;/li&gt;
      &lt;li id=&quot;WLeh&quot;&gt;&lt;code&gt;password&lt;/code&gt;: хэш пароля&lt;/li&gt;
      &lt;li id=&quot;UZ8B&quot;&gt;&lt;code&gt;birthday&lt;/code&gt;: 0&lt;/li&gt;
      &lt;li id=&quot;sGpV&quot;&gt;&lt;code&gt;email&lt;/code&gt;: отправленный email&lt;/li&gt;
      &lt;li id=&quot;FlIP&quot;&gt;&lt;code&gt;gender&lt;/code&gt;: &amp;quot;&amp;quot;&lt;/li&gt;
      &lt;li id=&quot;JSmp&quot;&gt;&lt;code&gt;date_start&lt;/code&gt;: 0&lt;/li&gt;
      &lt;li id=&quot;qg1E&quot;&gt;&lt;code&gt;hobby&lt;/code&gt;: &amp;quot;&amp;quot;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;AaXw&quot;&gt;&lt;strong&gt;Дополнительно:&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;8eGb&quot;&gt;
      &lt;li id=&quot;172o&quot;&gt;Пользователь появился в списке (проверка через GUI)&lt;/li&gt;
      &lt;li id=&quot;CiMt&quot;&gt;Можно войти под этим пользователем (email + пароль)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;PFGl&quot;&gt;2️⃣ Бизнес-логика из ТЗ&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;figure id=&quot;VHPf&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/2a/01/2a0154ea-c774-418e-ab14-0b8ef76c2e7f.png&quot; width=&quot;779&quot; /&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;NJkS&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e5/cb/e5cb4d28-f8e1-462f-a293-67301bde281b.png&quot; width=&quot;1476&quot; /&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;jAl4&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/21/25/21250aa3-bb91-4d13-b356-884e33c0f1c7.png&quot; width=&quot;1488&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;JOsv&quot;&gt;6️⃣ Тело запроса (Body)&lt;/h2&gt;
  &lt;h3 id=&quot;GlDp&quot;&gt;6.1 Перестановка мест параметров&lt;/h3&gt;
  &lt;ul id=&quot;mr6s&quot;&gt;
    &lt;li id=&quot;6ZDi&quot;&gt;JSON:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;1G8X&quot;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;Машенька{{$randomInt}}&amp;quot;,
  &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;p id=&quot;1kxT&quot;&gt;✅ Статус 200, корректный ответ&lt;/p&gt;
  &lt;ul id=&quot;pnFv&quot;&gt;
    &lt;li id=&quot;Fd0B&quot;&gt;Form-data → также статус 200&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;10v0&quot;&gt;6.2 Регистрозависимость&lt;/h3&gt;
  &lt;pre id=&quot;wd5U&quot;&gt;{
  &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,
  &amp;quot;NAME&amp;quot;: &amp;quot;Машенька{{$randomInt}}&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;
}
&lt;/pre&gt;
  &lt;p id=&quot;93gM&quot;&gt;✅ Статус 200, корректный ответ&lt;/p&gt;
  &lt;h3 id=&quot;NrYX&quot;&gt;6.3 Подмена метода&lt;/h3&gt;
  &lt;ul id=&quot;5yJq&quot;&gt;
    &lt;li id=&quot;wenj&quot;&gt;POST → GET&lt;br /&gt;❌ Статус 400, ошибка «Неправильный тип метода, нужно использовать POST»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;VUdm&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;m3yF&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b0/0a/b00a42df-d2f8-470e-aa94-3546ee11d831.png&quot; width=&quot;1520&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;1xem&quot;&gt;7️⃣ Вывод&lt;/h2&gt;
  &lt;ul id=&quot;u52f&quot;&gt;
    &lt;li id=&quot;mDVV&quot;&gt;Тестирование API ≈ тестированию GUI, но с доп. возможностями:&lt;/li&gt;
    &lt;ul id=&quot;QqwV&quot;&gt;
      &lt;li id=&quot;0dOG&quot;&gt;Менять порядок полей&lt;/li&gt;
      &lt;li id=&quot;gz59&quot;&gt;Менять имена ключей&lt;/li&gt;
      &lt;li id=&quot;X4kS&quot;&gt;Проверять разные типы методов&lt;/li&gt;
      &lt;li id=&quot;qmpf&quot;&gt;Ломать JSON/XML&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;6izb&quot;&gt;Всегда &lt;strong&gt;начинаем с бизнес-логики&lt;/strong&gt; (проверка по ТЗ, классы эквивалентности, граничные значения)&lt;/li&gt;
    &lt;li id=&quot;54o5&quot;&gt;Добавляем &lt;strong&gt;API-часть&lt;/strong&gt;:&lt;/li&gt;
    &lt;ul id=&quot;xWqx&quot;&gt;
      &lt;li id=&quot;8yus&quot;&gt;Перестановка параметров JSON и Form-data&lt;/li&gt;
      &lt;li id=&quot;apQc&quot;&gt;Регистрозависимость&lt;/li&gt;
      &lt;li id=&quot;QEV1&quot;&gt;Другой тип метода&lt;/li&gt;
      &lt;li id=&quot;edo6&quot;&gt;Проверка well-formed JSON/XML&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Cu1z&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;gbax&quot;&gt;не забудь заглянуть сюда&lt;/p&gt;
  &lt;p id=&quot;71dG&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;yHoi&quot;&gt;&lt;a href=&quot;https://youtu.be/M1kwub3H0AI?si=CvHAxad7bDq8Cnrd&quot; target=&quot;_blank&quot;&gt;https://youtu.be/M1kwub3H0AI?si=CvHAxad7bDq8Cnrd&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;SrfY&quot;&gt;&lt;br /&gt;и почитать вот тут: &lt;/p&gt;
  &lt;p id=&quot;Ca7o&quot;&gt;&lt;a href=&quot;https://habr.com/ru/companies/vk/articles/750096&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/companies/vk/articles/750096&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:ikQSIU-rw6N</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/ikQSIU-rw6N?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Тестирование бэка: Swagger. Postman</title><published>2025-10-20T08:12:20.810Z</published><updated>2025-10-20T08:12:20.810Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/30/ae/30ae4f8d-0a81-471f-960e-dd8939b9e1c7.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/webt/yb/fz/_k/ybfz_ksn6uvm5mkxoljdekflodi.jpeg&quot;&gt;Что такое API?</summary><content type="html">
  &lt;p id=&quot;szlm&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/464261/&quot; target=&quot;_blank&quot;&gt;Что такое API?&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;qPm5&quot;&gt;Что такое &lt;a href=&quot;https://teletype.in/@qafeelsgood/Swagger&quot; target=&quot;_blank&quot;&gt;Swagger&lt;/a&gt;?&lt;/p&gt;
  &lt;p id=&quot;huyb&quot;&gt;&lt;a href=&quot;https://habr.com/ru/companies/kolesa/articles/351250/&quot; target=&quot;_blank&quot;&gt;Postman&lt;/a&gt;: посмотреть, &lt;a href=&quot;https://www.youtube.com/watch?v=zfrQtU8eCEo&quot; target=&quot;_blank&quot;&gt;как отправлять запросы, настраивать url, метод, заголовки и тело запроса.&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;bJWU&quot;&gt;Виды авторизации: API токен, Bearer token, basic auth&lt;/p&gt;
  &lt;p id=&quot;Z4uO&quot;&gt;Вкладка Tests/Scripts в Postman: как добавить в запрос дополнительную проверку на код ответа, на время ожидания ответа.&lt;/p&gt;
  &lt;p id=&quot;sGNy&quot;&gt;Переменные в Postman: как добавить переменную окружения и использовать в запросе.&lt;/p&gt;
  &lt;p id=&quot;Jvu9&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/&quot; target=&quot;_blank&quot;&gt;Как в целом можно тестировать бэк&lt;/a&gt;: статья от Ольги Назиной.&lt;/p&gt;
  &lt;p id=&quot;nauT&quot;&gt;Чек-лист из этой статьи перенеси себе в шпаргалку и желательно запомнить несколько пунктов оттуда&lt;/p&gt;
  &lt;p id=&quot;lSp0&quot;&gt;Тестовый API &lt;a href=&quot;https://petstore.swagger.io/&quot; target=&quot;_blank&quot;&gt;https://petstore.swagger.io/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;ZFoB&quot;&gt;Создать коллекцию запросов в Postman, в которой ты сначала создаешь питомца, потом проверяешь его успешное создание GET-запросом, потом изменяешь его, опять проверяешь изменение гетом, потом удаляешь и проверяешь, что он удалился.&lt;br /&gt;То есть итоговая коллекция должна содержать 6 запросов.&lt;/p&gt;
  &lt;p id=&quot;i8Xt&quot;&gt;Добавь в каждый запрос любой дополнительный тест во вкладке Tests/Scripts или сгенерируй тесты автоматически через функцию &amp;quot;Generate tests&amp;quot; в меню коллекции.&lt;/p&gt;
  &lt;p id=&quot;gb7i&quot;&gt;Получившуюся коллекцию экспортируй в JSON-файл и прикрепи в эту таску&lt;/p&gt;
  &lt;p id=&quot;ytLQ&quot;&gt;UPD: Перед экспортом коллекции нужно жмякнуть кнопку &amp;quot;SAVE&amp;quot; во всех запросах по отдельности, иначе есть риск, что они экспортируются не доделанные&lt;/p&gt;
  &lt;p id=&quot;OLLR&quot;&gt;UPD2: Перед экспортом коллекции запусти полностью всю коллекцию по нажатию кнопки &amp;quot;Run collection&amp;quot;. Все запросы должны возвращать код 200 кроме последнего GET-запроса (он должен возвращать 404). Если у тебя получились другие коды ответа, то это значит, что где-то ошибка&lt;/p&gt;
  &lt;p id=&quot;XGgO&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;D6Br&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;onMP&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;KfAv&quot;&gt;Слово «API» мелькает в вакансиях даже для начинающих тестировщиков. То REST API, то SOAP API, то просто API. Что же это за зверь такой? Давайте разбираться!&lt;/p&gt;
  &lt;p id=&quot;v9z5&quot;&gt;— А зачем это мне? Я вообще-то web тестирую! Вот если пойду в автоматизацию, тогда да… Ну, еще это в enterprise тестируют, я слышал…&lt;/p&gt;
  &lt;p id=&quot;V3ES&quot;&gt;А вот и нет! Про API полезно знать любому тестировщику. Потому что по нему системы взаимодействуют между собой. И это взаимодействие вы видите каждый день даже на самых простых и захудалых сайтах.&lt;/p&gt;
  &lt;blockquote id=&quot;OxT7&quot;&gt;Любая оплата идет через API платежной системы. Купил билет в кино? Маечку в онлайн-магазине? Книжку? Как только жмешь «оплатить», сайт соединяет тебя с платежной системой.&lt;/blockquote&gt;
  &lt;p id=&quot;avhZ&quot;&gt;Но даже если у вас нет интеграции с другими системами, у вас всё равно есть API! Потому что система внутри себя тоже общается по api. И пока фронт-разработчик усиленно пилит GUI (графический интерфейс), вы можете:&lt;/p&gt;
  &lt;ul id=&quot;c42k&quot;&gt;
    &lt;li id=&quot;FSN9&quot;&gt;скучать в ожидании;&lt;/li&gt;
    &lt;li id=&quot;61AW&quot;&gt;проверять логику работы по API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;8kyj&quot;&gt;Конечно, я за второй вариант! Так что давайте разбираться, что же такое API. Можно посмотреть видео на &lt;a href=&quot;https://www.youtube.com/watch?v=QYg5z6EGOk4&quot; target=&quot;_blank&quot;&gt;youtube&lt;/a&gt;, или прочитать дальше в виде статьи.&lt;/p&gt;
  &lt;h2 id=&quot;2VBq&quot;&gt;Что такое API&lt;/h2&gt;
  &lt;figure id=&quot;jaiK&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/yb/fz/_k/ybfz_ksn6uvm5mkxoljdekflodi.jpeg&quot; width=&quot;386&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;JWmr&quot;&gt;&lt;em&gt;API (Application programming interface)&lt;/em&gt; — это контракт, который предоставляет программа. «Ко мне можно обращаться так и так, я обязуюсь делать то и это».&lt;/p&gt;
  &lt;p id=&quot;USN7&quot;&gt;Если переводить на русский, это было бы слово «договор». Договор между двумя сторонами, как договор на покупку машины:&lt;/p&gt;
  &lt;ul id=&quot;MAXk&quot;&gt;
    &lt;li id=&quot;tUK5&quot;&gt;мои обязанности — внести такую то сумму,&lt;/li&gt;
    &lt;li id=&quot;SczF&quot;&gt;обязанность продавца — дать машину.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Vi5G&quot;&gt;Перевести можно, да. Но никто так не делает ¯\_(ツ)_/¯&lt;/p&gt;
  &lt;p id=&quot;69iB&quot;&gt;Все используют слово «контракт». Так принято. К тому же это слово входит в название стиля разработки:&lt;/p&gt;
  &lt;ul id=&quot;JHBH&quot;&gt;
    &lt;li id=&quot;bKU1&quot;&gt;Code first — сначала пишем код, потом по нему генерируем контракт&lt;/li&gt;
    &lt;li id=&quot;QUxj&quot;&gt;Contract first — сначала создаем контракт, потом по нему пишем или генерируем код (в этой статье я буду говорить именно об этом стиле)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;soWM&quot;&gt;Мы же не говорим «контракт на продажу машины»? Вот и разработчики не говорят «договор». Негласное соглашение.&lt;/p&gt;
  &lt;h2 id=&quot;G4dH&quot;&gt;API — набор функций&lt;/h2&gt;
  &lt;p id=&quot;Ly5f&quot;&gt;Когда вы покупаете машину, вы составляете договор, в котором прописываете все важные для вас пункты. Точно также и между программами должны составляться договоры. Они указывают, как к той или иной программе можно обращаться.&lt;/p&gt;
  &lt;p id=&quot;6SwC&quot;&gt;Соответственно, API отвечает на вопрос “Как ко мне, к моей системе можно обратиться?”, и включает в себя:&lt;/p&gt;
  &lt;ul id=&quot;iw4z&quot;&gt;
    &lt;li id=&quot;R8x9&quot;&gt;саму операцию, которую мы можем выполнить,&lt;/li&gt;
    &lt;li id=&quot;fdUS&quot;&gt;данные, которые поступают на вход,&lt;/li&gt;
    &lt;li id=&quot;ZYJZ&quot;&gt;данные, которые оказываются на выходе (контент данных или сообщение об ошибке).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;XVup&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/2x/rv/qa/2xrvqa5qt01hubxsaytf2sgi_ia.png&quot; width=&quot;638&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Wu3u&quot;&gt;Тут вы можете мне сказать:&lt;/p&gt;
  &lt;p id=&quot;2ppy&quot;&gt;— Хмм, погоди. Операция, данные на входе, данные на выходе — как-то всё это очень сильно похоже на описание функции!&lt;/p&gt;
  &lt;p id=&quot;1aPv&quot;&gt;&lt;em&gt;Если вы когда-то сталкивались с разработкой или просто изучали язык программирования, вы наверняка знаете, что такое функция. Фактически у нас есть данные на входе, есть данные на выходе, и некая магия, которая преобразует одно в другое.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;8mKa&quot;&gt;И да! Вы будете правы в том, что определения похожи. Почему? Да потому что API — это набор функций. Это может быть одна функция, а может быть много.&lt;/p&gt;
  &lt;figure id=&quot;gmgN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/sn/jw/46/snjw46wwnvuatj0wkghyuueofao.png&quot; width=&quot;655&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;0TYt&quot;&gt;Как составляется набор функций&lt;/h2&gt;
  &lt;p id=&quot;aM3l&quot;&gt;Да без разницы как. Как разработчик захочет, так и сгруппирует. Например, можно группировать API по функционалу. То есть:&lt;/p&gt;
  &lt;ul id=&quot;N3TF&quot;&gt;
    &lt;li id=&quot;56aC&quot;&gt;отдельно API для входа в систему, где будет регистрация и авторизация;&lt;/li&gt;
    &lt;li id=&quot;KKtf&quot;&gt;отдельно API для отчетности — отчет 1, отчет 2, отчет 3… отчет N. Для разных отчетов у нас разные формулы = разные функции. И все мы их собираем в один набор, api для отчетности.&lt;/li&gt;
    &lt;li id=&quot;NeR9&quot;&gt;отдельно API платежек — для работы с каждым банком своя функция.&lt;/li&gt;
    &lt;li id=&quot;ggLs&quot;&gt;...&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;5lX5&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/xh/4z/oz/xh4zozptcyhurgnczngm9uqhje0.png&quot; width=&quot;628&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;GlX7&quot;&gt;Можно не группировать вообще, а делать одно общее API.&lt;/p&gt;
  &lt;p id=&quot;gObi&quot;&gt;Можно сделать одно общее API, а остальные «под заказ». Если у вас коробочный продукт, то в него обычно входит набор стандартных функций. А любые хотелки заказчиков выносятся отдельно.&lt;/p&gt;
  &lt;figure id=&quot;cUB7&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/lf/jh/o6/lfjho6yakkb1jciqvtti0wonj00.png&quot; width=&quot;628&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Z2TG&quot;&gt;Получается, что в нашей системе есть несколько разных API, на каждое из которых у нас написан контракт. В каждом контракте четко прописано, какие операции можно выполнять, какие функции там будут&lt;/p&gt;
  &lt;figure id=&quot;KEw0&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/xo/nv/29/xonv293kj3r1fiwniobwatdn8f0.png&quot; width=&quot;538&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Eh5Z&quot;&gt;И конечно, функции можно переиспользовать. То есть одну и ту же функцию можно включать в разные наборы, в разные апи. Никто этого не запрещает.&lt;/p&gt;
  &lt;figure id=&quot;RrXm&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/uj/hm/wa/ujhmwa-iv-okyrifyzqpnu3acsw.png&quot; width=&quot;605&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;v8Cn&quot;&gt;Получается, что разработчик придумывает, какое у него будет API. Либо делает общее, либо распределяет по функционалу или каким-то своим критериям, и в каждое апи добавляет тот набор функций, который ему необходим.&lt;/p&gt;
  &lt;h2 id=&quot;BUNl&quot;&gt;При чем тут слово «интерфейс»&lt;/h2&gt;
  &lt;blockquote id=&quot;kMiZ&quot;&gt;— Минуточку, Оля! Ты же сама выше писала, что API — это Application programming interface. Почему ты тогда говоришь о контракте, хотя там слово интерфейс?&lt;/blockquote&gt;
  &lt;p id=&quot;WXP9&quot;&gt;Да потому, что в программировании контракт — это и есть интерфейс. В классическом описании ООП (объектно-ориентированного программирования) есть 3 кита:&lt;/p&gt;
  &lt;ol id=&quot;Tb4R&quot;&gt;
    &lt;li id=&quot;A8jp&quot;&gt;Инкапсуляция&lt;/li&gt;
    &lt;li id=&quot;biSU&quot;&gt;Наследование&lt;/li&gt;
    &lt;li id=&quot;rZdf&quot;&gt;Полиморфизм&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;DaUa&quot;&gt;Инкапсуляция — это когда мы скрываем реализацию. Для пользователя все легко и понятно. Нажал на кнопочку — получил отчет. А как это работает изнутри — ему все равно. Какая база данных скрыта под капотом? Oracle? MySQL? На каком языке программирования написана программа? Как именно организован код? Не суть. Программа предоставляет интерфейс, им он и пользуется.&lt;/p&gt;
  &lt;p id=&quot;bWoN&quot;&gt;Не всегда программа предоставляет именно графический интерфейс. Это может быть SOAP, REST интерфейс, или другое API. Чтобы использовать этот интерфейс, вы должны понимать:&lt;/p&gt;
  &lt;ul id=&quot;s0bN&quot;&gt;
    &lt;li id=&quot;qQbY&quot;&gt;что подать на вход;&lt;/li&gt;
    &lt;li id=&quot;LYKD&quot;&gt;что получается на выходе;&lt;/li&gt;
    &lt;li id=&quot;kuOM&quot;&gt;какие исключения нужно обработать.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;IwPL&quot;&gt;Пользователи работают с &lt;em&gt;GUI — graphical user interface&lt;/em&gt;. Программы работают с &lt;em&gt;API — Application programming interface&lt;/em&gt;. Им не нужна графика, только контракт.&lt;/p&gt;
  &lt;h1 id=&quot;xacR&quot;&gt;Как вызывается API&lt;/h1&gt;
  &lt;p id=&quot;2myb&quot;&gt;Вызвать апи можно как напрямую, так и косвенно.&lt;/p&gt;
  &lt;p id=&quot;IhZ7&quot;&gt;Напрямую:&lt;/p&gt;
  &lt;ol id=&quot;cqPp&quot;&gt;
    &lt;li id=&quot;7Usz&quot;&gt;Система вызывает функции внутри себя&lt;/li&gt;
    &lt;li id=&quot;YYNr&quot;&gt;Система вызывает метод другой системы&lt;/li&gt;
    &lt;li id=&quot;lU1d&quot;&gt;Человек вызывает метод&lt;/li&gt;
    &lt;li id=&quot;800S&quot;&gt;Автотесты дергают методы&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;I1QL&quot;&gt;Косвенно:&lt;/p&gt;
  &lt;ol id=&quot;PKoS&quot;&gt;
    &lt;li id=&quot;wTH9&quot;&gt;Пользователь работает с GUI&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h2 id=&quot;CKCk&quot;&gt;Вызов API напрямую&lt;/h2&gt;
  &lt;h3 id=&quot;yYVn&quot;&gt;1. Система вызывает функции внутри себя&lt;/h3&gt;
  &lt;p id=&quot;uQtI&quot;&gt;Разные части программы как-то общаются между собой. Они делают это на программном уровне, то есть на уровне API!&lt;/p&gt;
  &lt;p id=&quot;lr90&quot;&gt;Это самый «простой» в использовании способ, потому что автор API, которое вызывается — разработчик. И он же его потребитель! А значит, проблемы с неактуальной документацией нет =)&lt;/p&gt;
  &lt;p id=&quot;5cS9&quot;&gt;Шучу, проблемы с документацией есть всегда. Просто в этом случае в качестве документации будут комментарии в коде. А они, увы, тоже бывают неактуальны. Или разработчики разные, или один, но уже забыл, как делал исходное api и как оно должно работать…&lt;/p&gt;
  &lt;h3 id=&quot;nFjH&quot;&gt;2. Система вызывает метод другой системы&lt;/h3&gt;
  &lt;p id=&quot;KsT0&quot;&gt;А вот это типичный кейс, которые тестируют тестировщики в интеграторах. Или тестировщики, которые проверяют интеграцию своей системы с чужой. &lt;/p&gt;
  &lt;p id=&quot;2ANv&quot;&gt;Одна система дергает через api какой-то метод другой системы. Она может попытаться получить данные из другой системы. Или наоборот, отправить данные в эту систему.&lt;/p&gt;
  &lt;blockquote id=&quot;txPK&quot;&gt;Допустим, я решила подключить &lt;a href=&quot;https://dadata.ru/suggestions/&quot; target=&quot;_blank&quot;&gt;подсказки из Дадаты&lt;/a&gt; к своему интернет-магазинчику, чтобы пользователь легко ввел адрес доставки. &lt;br /&gt;&lt;br /&gt;Я подключаю подсказки по API. И теперь, когда пользователь начинает вводить адрес на &lt;em&gt;моем&lt;/em&gt; сайте, он видит подсказки из &lt;em&gt;Дадаты&lt;/em&gt;. Как это получается:&lt;br /&gt;&lt;br /&gt;Он вводит букву на моем сайтеМой сайт отправляет запрос в подсказки Дадаты по APIДадата возвращает ответМой сайт его обрабатывает и отображает результат пользователю&lt;br /&gt;Вон сколько шагов получилось! И так на каждый введенный символ. Пользователь не видит этого взаимодействия, но оно есть.&lt;/blockquote&gt;
  &lt;p id=&quot;bRBO&quot;&gt;И, конечно, не забываем про кейс, когда мы разрабатываем именно API-метод. Который только через SOAP и можно вызвать, в интерфейсе его нигде нет. Что Заказчик заказал, то мы и сделали ¯\_(ツ)_/¯&lt;/p&gt;
  &lt;blockquote id=&quot;zHHS&quot;&gt;Пример можно посмотреть в Users. Метод &lt;a href=&quot;https://testbase.atlassian.net/wiki/spaces/USERS/pages/1249378773/MagicSearch&quot; target=&quot;_blank&quot;&gt;MagicSearch&lt;/a&gt; создан на основе реальных событий. Хотя надо признать, в оригинале логика еще замудренее была, я то под свой сайт подстраивала. &lt;br /&gt;&lt;br /&gt;Но тут фишка в том, что в самой системе в пользовательском интерфейсе есть только обычный поиск, просто строка ввода. Ну, может, парочка фильтров. А вот для интеграции нужна была целая куча доп возможностей, что и было сделано через SOAP-метод. &lt;br /&gt;&lt;br /&gt;Функционал супер-поиска доступен только по API, пользователь в интерфейсе его никак не пощупает.&lt;/blockquote&gt;
  &lt;p id=&quot;EmEn&quot;&gt;В этом случае у вас обычно есть ТЗ, согласно которому работает API-метод. Ваша задача — проверить его. Типичная задача тестировщика, просто добавьте к стандартным тестам на тест-дизайн особенности тестирования API, и дело в шляпе!&lt;/p&gt;
  &lt;p id=&quot;RD4n&quot;&gt;&lt;em&gt;(что именно надо тестировать в API — я расскажу отдельной статьей чуть позднее)&lt;/em&gt;&lt;/p&gt;
  &lt;h3 id=&quot;TtBK&quot;&gt;3. Человек вызывает метод&lt;/h3&gt;
  &lt;p id=&quot;jh1x&quot;&gt;Причины разные:&lt;/p&gt;
  &lt;ol id=&quot;qzGv&quot;&gt;
    &lt;li id=&quot;p0dO&quot;&gt;Для ускорения работы&lt;/li&gt;
    &lt;li id=&quot;FzPz&quot;&gt;Для локализации бага (проблема где? На сервере или клиенте?)&lt;/li&gt;
    &lt;li id=&quot;8oPz&quot;&gt;Для проверки логики без докруток фронта&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;snL8&quot;&gt;Если система предоставляет API, обычно проще дернуть его, чем делать то же самое через графический интерфейс. Тем более что вызов API можно сохранить в инструменте. Один раз сохранил — на любой базе применяешь, пусть даже она по 10 раз в день чистится.&lt;/p&gt;
  &lt;blockquote id=&quot;3C93&quot;&gt;Для примера снова идем в &lt;a href=&quot;https://okiseleva.blogspot.com/2017/04/users-soap-rest.html&quot; target=&quot;_blank&quot;&gt;Users&lt;/a&gt;. Если мы хотим создать пользователя, надо заполнить уйму полей!&lt;/blockquote&gt;
  &lt;figure id=&quot;t0Yv&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/0g/ra/yn/0graynfv0qexhh4iubtecyyzepo.png&quot; width=&quot;730&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;GOMi&quot;&gt;Конечно, это можно сделать с помощью специальных плагинов типа &lt;a href=&quot;https://okiseleva.blogspot.com/2019/04/form-filler.html&quot; target=&quot;_blank&quot;&gt;Form Filler&lt;/a&gt;. Но что, если вам нужны адекватные тестовые данные под вашу систему? И на русском языке? &lt;br /&gt;&lt;br /&gt;Заполнение полей вручную — грустно и уныло! А уж если это надо повторять каждую неделю или день на чистой тестовой базе — вообще кошмар. Это сразу первый приоритет на автоматизацию рутинных действий.&lt;br /&gt;&lt;br /&gt;И в данном случае роль автоматизатора выполняет… Postman. Пользователя можно создать через REST-запрос &lt;a href=&quot;https://testbase.atlassian.net/wiki/spaces/USERS/pages/871924071/CreateUser&quot; target=&quot;_blank&quot;&gt;CreateUser&lt;/a&gt;. Один раз прописали нормальные “как настоящие” данные, каждый раз пользуемся. Профит!&lt;br /&gt;&lt;br /&gt;Вместо ручного заполнения формы (1 минута бездумного заполнения полей значениями «лпрулпк») получаем 1 секунду нажатия на кнопку «Send». При этом значения будут намного адекватнее.&lt;br /&gt;&lt;br /&gt;А еще в постмане можно сделать отдельную папку подготовки тестовой базы, напихать туда десяток запросов. И вот уже на любой базе за пару секунд вы получаете столько данных, сколько вручную вбивали бы часами!&lt;/blockquote&gt;
  &lt;p id=&quot;IN0S&quot;&gt;Если вы нашли баг и не понимаете, на кого его вешать — разработчика front-end или back-end, уберите все лишнее. Вызовите метод без графического интерфейса. А еще вы можете тестировать логику программы, пока интерфейс не готов или сломан.&lt;/p&gt;
  &lt;h3 id=&quot;qf8W&quot;&gt;4. Автотесты дергают методы&lt;/h3&gt;
  &lt;p id=&quot;bk7e&quot;&gt;Есть типичная пирамида автоматизации:&lt;/p&gt;
  &lt;ul id=&quot;na4p&quot;&gt;
    &lt;li id=&quot;oRHZ&quot;&gt;GUI-тесты — честный тест, «как это делал бы пользователь».&lt;/li&gt;
    &lt;li id=&quot;WIC5&quot;&gt;API-тесты — опускаемся на уровень ниже, выкидывая лишнее.&lt;/li&gt;
    &lt;li id=&quot;tNz1&quot;&gt;Unit-тесты — тесты на отдельную функцию&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;eO9q&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/hp/yc/ng/hpycngdplj56-mdkhf2tropqvhq.png&quot; width=&quot;471&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;fLnk&quot;&gt;Слово API как бы намекает на то, что будет использовано в тестах ツ&lt;/p&gt;
  &lt;blockquote id=&quot;CAhz&quot;&gt;Допустим, у нас есть:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;операция&lt;/strong&gt;: загрузка отчета; &lt;strong&gt;на входе&lt;/strong&gt;: данные из ручных или автоматических корректировок или из каких-то других мест; &lt;strong&gt;на выходе&lt;/strong&gt;: отчет, построенный по неким правилам&lt;br /&gt;Правила построения отчета:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Ячейка 1&lt;/strong&gt;: Х — Y&lt;strong&gt;Ячейка 2&lt;/strong&gt;: Z * 6...&lt;/blockquote&gt;
  &lt;figure id=&quot;R5VL&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/p-/hw/lf/p-hwlfdcpoxryvrxjvlcg43h7ma.png&quot; width=&quot;656&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;vFxc&quot;&gt;&lt;strong&gt;GUI-тесты&lt;/strong&gt; — честный тест, робот делает все, что делал бы пользователь. Открывает браузер, тыкает на кнопочки… Но если что-то упадет, будете долго разбираться, где именно.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;API-тесты&lt;/strong&gt; — все то же самое, только без браузера. Мы просто подаем данные на вход и проверяем данные на выходе. Например, можно внести итоговый ответ в эксельку, и пусть робот выверяет ее, правильно ли заполняются данные? Локализовать проблему становится проще.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Unit-тесты&lt;/strong&gt; — это когда мы проверяем каждую функцию отдельно. Отдельно смотрим расчет для ячейки 1, отдельно — для ячейки 2, и так далее. Такие тесты шустрее всего гоняются и баги по ним легко локализовать.&lt;/blockquote&gt;
  &lt;h2 id=&quot;MpIs&quot;&gt;Косвенный вызов API&lt;/h2&gt;
  &lt;p id=&quot;Bagc&quot;&gt;Когда пользователь работает с GUI, на самом деле он тоже работает с API. Просто не знает об этом, ему это просто не нужно.&lt;/p&gt;
  &lt;p id=&quot;bQi6&quot;&gt;То есть когда пользователь открывает систему и пытается загрузить отчет, ему не важно, как работает система, какой там magic внутри. У него есть кнопочка «загрузить отчет», на которую он и нажимает. Пользователь работает через GUI (графический пользовательский интерфейс).&lt;/p&gt;
  &lt;figure id=&quot;rE0C&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/-o/7i/b_/-o7ib_j6tnrt1rz3axldz8vqmxq.png&quot; width=&quot;650&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;5iK2&quot;&gt;Но на самом деле под этим графическим пользовательским интерфейсом находится API. И когда пользователь нажимает на кнопочку, кнопочка вызывает функцию построения отчета.&lt;/p&gt;
  &lt;figure id=&quot;IS1e&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/x3/co/rs/x3corsskpydptgjoaebtgrqvhbi.png&quot; width=&quot;656&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;djxs&quot;&gt;А функция построения отчета уже может вызывать 10 разных других функций, если ей это необходимо. &lt;/p&gt;
  &lt;p id=&quot;z442&quot;&gt;И вот уже пользователь видит перед собой готовый отчет. Он вызвал сложное API, даже не подозревая об этом!&lt;/p&gt;
  &lt;h1 id=&quot;ysE3&quot;&gt;Что значит «Тестирование API»&lt;/h1&gt;
  &lt;p id=&quot;VeTa&quot;&gt;В первую очередь, мы подразумеваем тестирование ЧЕРЕЗ API. «Тестирование API» — общеупотребимый термин, так действительно говорят, но технически термин некорректен. Мы не тестируем API, мы не тестируем GUI (графический интерфейс). Мы тестируем какую-то функциональность через графический или программный интерфейс.&lt;/p&gt;
  &lt;p id=&quot;YmTa&quot;&gt;Но это устоявшееся выражение. Можно использовать его и говорить “тестирование API”. И когда мы про это говорим, мы имеем в виду:&lt;/p&gt;
  &lt;ul id=&quot;0WgU&quot;&gt;
    &lt;li id=&quot;5ka7&quot;&gt;автотесты на уровне API&lt;/li&gt;
    &lt;li id=&quot;b4Pd&quot;&gt;или интеграцию между двумя разными системами.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;A5hJ&quot;&gt;Интеграция — когда одна система общается с другой по какому-то протоколу передачи данных. Это называется Remote API, то есть общение по сети, по некоему протоколу (HTTP, JMS и т.д.). В противовес ему есть еще Local API (он же «Shared memory API») — это то API, по которому программа общается сама с собой или общается с другой программой внутри одной виртуальной памяти.&lt;/p&gt;
  &lt;figure id=&quot;GFiT&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/b3/of/e9/b3ofe9co4ncbwachodnenynwsxu.png&quot; width=&quot;644&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;sVM6&quot;&gt;Когда мы говорим про тестирование API, чаще всего мы подразумеваем тестирование Remote API. Когда у нас есть две системы, находящихся на разных компьютерах, которые как-то между собой общаются.&lt;/p&gt;
  &lt;p id=&quot;dnlj&quot;&gt;И если вы видите в вакансии «тестирование API», скорее всего это подразумевает умение вызвать SOAP или REST сервис и протестировать его. Хотя всегда стоит уточнить!&lt;/p&gt;
  &lt;h1 id=&quot;I6GH&quot;&gt;Резюме&lt;/h1&gt;
  &lt;p id=&quot;7YHr&quot;&gt;&lt;em&gt;API (Application programming interface)&lt;/em&gt; — это контракт, который предоставляет программа. «Ко мне можно обращаться так и так, я обязуюсь делать то и это».&lt;/p&gt;
  &lt;p id=&quot;BteL&quot;&gt;Контракт включает в себя:&lt;/p&gt;
  &lt;ul id=&quot;3J31&quot;&gt;
    &lt;li id=&quot;pTdR&quot;&gt;саму операцию, которую мы можем выполнить,&lt;/li&gt;
    &lt;li id=&quot;BIVJ&quot;&gt;данные, которые поступают на вход,&lt;/li&gt;
    &lt;li id=&quot;FsqS&quot;&gt;данные, которые оказываются на выходе (контент данных или сообщение об ошибке).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;eTrk&quot;&gt;Вызвать API можно как напрямую, так и косвенно:&lt;/p&gt;
  &lt;ol id=&quot;bQBO&quot;&gt;
    &lt;li id=&quot;S5k7&quot;&gt;Система вызывает функции внутри себя&lt;/li&gt;
    &lt;li id=&quot;u8bw&quot;&gt;Система вызывает метод другой системы&lt;/li&gt;
    &lt;li id=&quot;ny4t&quot;&gt;Человек вызывает метод&lt;/li&gt;
    &lt;li id=&quot;u545&quot;&gt;Автотесты дергают методы&lt;/li&gt;
    &lt;li id=&quot;97Yv&quot;&gt;Пользователь работает с GUI&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;fKqZ&quot;&gt;Когда говорят про API с тестировщиком, обсуждают два варианта:&lt;/p&gt;
  &lt;ul id=&quot;Dasl&quot;&gt;
    &lt;li id=&quot;QnTc&quot;&gt;автотесты на уровне API (умение автоматизировать)&lt;/li&gt;
    &lt;li id=&quot;IwKz&quot;&gt;интеграцию между двумя разными системами (обычно SOAP или REST, то есть работу в SOAP Ui или Postman).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;a2fm&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;rIR2&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;xLPS&quot;&gt;&lt;/p&gt;
  &lt;h1 id=&quot;FqE6&quot;&gt;Тестируем с помощью Swagger&lt;/h1&gt;
  &lt;section&gt;
    &lt;p id=&quot;R1V4&quot;&gt;&lt;strong&gt;API (Application Programming Interface) &lt;/strong&gt;— это набор процедур, протоколов и инструментов, позволяющих разным программным приложениям общаться между собой. API дает возможность осуществлять взаимодействие с различными сервисами и приложениями, используя специальные запросы и ответы.&lt;/p&gt;
    &lt;h2 id=&quot;M54b&quot;&gt;Наиболее популярные и эффективные инструменты для тестирования API:&lt;/h2&gt;
    &lt;ul id=&quot;3tEw&quot;&gt;
      &lt;li id=&quot;rJrL&quot;&gt;&lt;strong&gt;Postman &lt;/strong&gt;— это инструмент для тестирования API, позволяющий создавать, отправлять и тестировать HTTP-запросы и проверять ответы на них.&lt;/li&gt;
      &lt;li id=&quot;tS5R&quot;&gt;&lt;strong&gt;Swagger&lt;/strong&gt; — это инструмент для документирования и тестирования API, позволяющий автоматически создавать документацию API из описания структуры API в формате YAML или JSON файла.&lt;/li&gt;
      &lt;li id=&quot;VtrA&quot;&gt;&lt;strong&gt;SoapUI&lt;/strong&gt; — это инструмент для тестирования веб-сервисов, позволяющий создавать и выполнять тесты на протоколе SOAP.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;ul id=&quot;JNBJ&quot;&gt;
      &lt;li id=&quot;NI4H&quot;&gt;&lt;strong&gt;Fiddler&lt;/strong&gt; — это инструмент для анализа и отладки HTTP-трафика между веб-браузером и веб-сервером. С точки зрения тестирования API Fiddler позволяет перехватывать, анализировать и модифицировать HTTP-запросы и ответы, передаваемые между клиентом и сервером. Это позволяет тестировщикам осуществлять валидацию запросов и ответов, проверять правильность передачи параметров, куки и другие элементы запросов, отслеживать проблемы с трафиком, а также выявлять и локализовать проблемы с API.&lt;/li&gt;
      &lt;li id=&quot;bQc1&quot;&gt;&lt;strong&gt;JMeter&lt;/strong&gt; — это инструмент для тестирования производительности и функциональности программного обеспечения, который может использоваться для тестирования API. С точки зрения тестирования API, JMeter является инструментом, позволяющим создавать запросы к API, анализировать ответы и оценивать производительность и функциональность API. JMeter может использоваться для создания нагрузки на API, чтобы измерить производительность, время ответа и другие метрики, которые помогут обнаружить ошибки в API и улучшить его производительность и функциональность.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;p id=&quot;Y4rT&quot;&gt;Вышеперечисленные инструменты позволяют тестировщикам эффективно и быстро проверять API на разных этапах разработки, чтобы обеспечить его соответствие требованиям и качеству.&lt;/p&gt;
    &lt;p id=&quot;stNy&quot;&gt;В данной публикации рассмотрим подробнее Swagger, позволяющий создавать, документировать и тестировать API. С помощью Swagger можно узнать доступные эндпоинты, параметры запросов и формат ответов.&lt;/p&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h2 id=&quot;ChEd&quot;&gt;О Swagger&lt;/h2&gt;
    &lt;p id=&quot;1GoZ&quot;&gt;Swagger разработан компанией Reverb Technologies, основанной в 2010 году в Миннеаполисе, США. Основателями компании были Тони Тамбурино (Tony Tambourine), Райан Дювелл (Ryan Duell) и Ник Селлер (Nick Sutterer).&lt;/p&gt;
    &lt;p id=&quot;z1Hi&quot;&gt;Swagger создан в целях облегчения работы разработчиков API и обеспечения большего взаимодействия между разработчиками и потребителями API. В 2015 году Swagger был перенесен в сообщество OpenAPI Initiative, которое является частью Linux Foundation, где его разработка и поддержка продолжаются по сей день.&lt;/p&gt;
    &lt;h3 id=&quot;GGIL&quot;&gt;Преимущества и особенности Swagger:&lt;/h3&gt;
    &lt;ul id=&quot;ZveP&quot;&gt;
      &lt;li id=&quot;1gnm&quot;&gt;Легкость использования: Swagger имеет простой и легкий интерфейс, позволяющий разработчикам быстро и легко создавать и документировать API.&lt;/li&gt;
      &lt;li id=&quot;fTmL&quot;&gt;Автоматическое поколение документации: Swagger позволяет автоматически создавать документацию для API с использованием стандарта OpenAPI. Это позволяет потребителям API быстро и легко понять, как взаимодействовать с API и использовать его функциональность.&lt;/li&gt;
      &lt;li id=&quot;4M4j&quot;&gt;Поддержка различных языков программирования: Swagger поддерживает многие языки программирования, что позволяет разработчикам использовать его для документирования API на любом языке программирования.&lt;/li&gt;
      &lt;li id=&quot;sy7S&quot;&gt;Поддержка открытых стандартов: Swagger основан на стандартах OpenAPI, которые поддерживаются большим количеством инструментов и платформ, что позволяет разработчикам использовать его с любым другим инструментом или платформой, поддерживающими стандарты OpenAPI.&lt;/li&gt;
      &lt;li id=&quot;npHP&quot;&gt;Тестирование и валидация API: Swagger позволяет разработчикам тестировать и валидировать API, обеспечивая большую надежность и качество работы API.&lt;/li&gt;
      &lt;li id=&quot;SjvM&quot;&gt;Расширяемость Swagger имеет открытый код и активное сообщество разработчиков, что позволяет им расширять и настраивать его под свои нужды.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p id=&quot;vyGM&quot;&gt;Для каждого из методов HTTP Swagger позволяет описать параметры запросов и формат ответов.&lt;/p&gt;
    &lt;p id=&quot;368n&quot;&gt;Например, для метода GET можно описать параметры запросов, такие как query string parameters, headers, или path parameters, и формат ответа, такой как JSON или XML. Аналогично Swagger позволяет описывать параметры и формат ответов для методов POST, PUT и DELETE. Это обеспечивает понятность и консистентность описания API и позволяет разработчикам эффективно использовать API в своих приложениях.&lt;/p&gt;
    &lt;p id=&quot;OQqx&quot;&gt;Примеры описания параметров запросов и формат ответов можно найти &lt;a href=&quot;https://petstore.swagger.io/&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
    &lt;figure id=&quot;EhJ9&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/2e/f2/2ef20d71-1857-429f-89ea-784187804fc0.png&quot; width=&quot;1977&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h2 id=&quot;7ulx&quot;&gt;рПримеры методов&lt;/h2&gt;
    &lt;h3 id=&quot;c4io&quot;&gt;POST метод (создание объекта):&lt;/h3&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;figure id=&quot;P6yT&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/c3/93/c39317cd-7075-4c2b-a84f-2e6af3317567.png&quot; width=&quot;1981&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;p id=&quot;lcIP&quot;&gt;Результат после отправки запроса:&lt;/p&gt;
    &lt;figure id=&quot;94Oy&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img2.teletype.in/files/d5/9b/d59bbc6b-fae0-4bc2-a07d-a27f04971954.png&quot; width=&quot;1973&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h3 id=&quot;pVdX&quot;&gt;GET метод (получение данных):&lt;/h3&gt;
    &lt;figure id=&quot;mzNW&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img3.teletype.in/files/a9/1d/a91d5548-63fc-4d41-ab68-d0428a6f5b4f.png&quot; width=&quot;1834&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h3 id=&quot;4KDo&quot;&gt;PUT метод (редактирование данных):&lt;/h3&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;figure id=&quot;kQXx&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/05/c6/05c615eb-1603-4878-b2d4-6a6a9d246fe3.png&quot; width=&quot;1840&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;p id=&quot;suyC&quot;&gt;Результат после отправки запроса:&lt;/p&gt;
    &lt;figure id=&quot;x8wW&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/00/48/00487df7-1ebc-4b2c-bd68-e74e24cea69a.png&quot; width=&quot;1977&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h3 id=&quot;xSDq&quot;&gt;Метод DELETE (удаление объекта):&lt;/h3&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;figure id=&quot;9Ajv&quot; class=&quot;m_original&quot;&gt;
      &lt;img src=&quot;https://img1.teletype.in/files/cf/2a/cf2a64cf-7a30-4fb8-ab4f-ddfe89eab849.png&quot; /&gt;
    &lt;/figure&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;p id=&quot;VtEZ&quot;&gt;Swagger является важным инструментом для тестировщиков, так как позволяет генерировать документацию для API и исследовать его функционал, что помогает увеличивать производительность тестирования API и эффективнее взаимодействовать с командой разработчиков во время процесса разработки и тестирования API.&lt;/p&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h2 id=&quot;4Mb9&quot;&gt;Полезные материалы:&lt;/h2&gt;
    &lt;ul id=&quot;D9Gd&quot;&gt;
      &lt;li id=&quot;fyHP&quot;&gt;&lt;a href=&quot;https://swagger.io/docs/&quot; target=&quot;_blank&quot;&gt;Официальная документация&lt;/a&gt; Swagger: на сайте Swagger есть подробная документация с описанием различных функций и возможностей.&lt;/li&gt;
      &lt;li id=&quot;RL91&quot;&gt;&lt;a href=&quot;https://editor.swagger.io/&quot; target=&quot;_blank&quot;&gt;Swagger Editor&lt;/a&gt;: это бесплатный онлайн-редактор Swagger, позволяющий создавать, редактировать и проверять файл Swagger в режиме реального времени.&lt;/li&gt;
      &lt;li id=&quot;fqGm&quot;&gt;&lt;a href=&quot;https://swagger.io/tools/swaggerhub/&quot; target=&quot;_blank&quot;&gt;SwaggerHub&lt;/a&gt;: это интерактивная среда Swagger, которая позволяет создавать, документировать и публиковать свои API, а также общаться с другими разработчиками API.&lt;/li&gt;
      &lt;li id=&quot;lrQ6&quot;&gt;&lt;a href=&quot;https://swagger.io/tools/swagger-ui/&quot; target=&quot;_blank&quot;&gt;Swagger UI&lt;/a&gt;: это интерактивный пользовательский интерфейс, который позволяет тестировать API непосредственно из браузера. Вы можете выполнять запросы API и просматривать ответы в разных форматах.&lt;/li&gt;
      &lt;li id=&quot;4lYp&quot;&gt;&lt;a href=&quot;https://swagger.io/docs/open-source-tools/swagger-codegen/&quot; target=&quot;_blank&quot;&gt;Swagger Codegen&lt;/a&gt;: это инструмент, позволяющий сгенерировать клиентский код для вашего API на основе файла Swagger. Вы можете выбрать язык программирования и тип клиента для создания кода, который соответствует вашим потребностям.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;p id=&quot;6UfN&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;pjuO&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;RvdN&quot;&gt;&lt;/p&gt;
  &lt;figure id=&quot;tFFw&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/40e/c7f/b4f/40ec7fb4f579c099e14f300685f2222c.png&quot; width=&quot;1505&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;iN8m&quot;&gt;“Разработка API сложна, Postman делает её лёгкой” © Postdot Technologies, Inc&lt;/blockquote&gt;
  &lt;p id=&quot;FWWJ&quot;&gt;Когда видишь описание инструментов Postman — захватывает дух, просыпается чувство всевластия над своим будущим детищем. Кажется, что и взрощенные в прошлом &amp;quot;монстры&amp;quot; наконец-то падут перед тобой!&lt;/p&gt;
  &lt;p id=&quot;ZXhD&quot;&gt;В этой статье мы расскажем о Postman и попробуем написать свой первый скрипт.&lt;/p&gt;
  &lt;h2 id=&quot;postman&quot;&gt;Postman&lt;/h2&gt;
  &lt;p id=&quot;IEij&quot;&gt;Основное предназначение приложения — создание коллекций с запросами к вашему API. Любой разработчик или тестировщик, открыв коллекцию, сможет с лёгкостью разобраться в работе вашего сервиса. Ко всему прочему, Postman позволяет проектировать дизайн API и создавать на его основе Mock-сервер. Вашим разработчикам больше нет необходимости тратить время на создание &amp;quot;заглушек&amp;quot;. Реализацию сервера и клиента можно запустить одновременно. Тестировщики могут писать тесты и производить автоматизированное тестирование прямо из Postman. А инструменты для автоматического документирования по описаниям из ваших коллекций сэкономят время на ещё одну &amp;quot;полезную фичу&amp;quot;. Есть кое-что и для администраторов — авторы предусмотрели возможность создания коллекций для мониторинга сервисов.&lt;/p&gt;
  &lt;h2 id=&quot;vvedenie&quot;&gt;Введение&lt;/h2&gt;
  &lt;figure id=&quot;AXrQ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/cd1/a83/a4f/cd1a83a4fbe0bf2dceb2d7b3a8f1d494.png&quot; width=&quot;1301&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mR90&quot;&gt;&lt;em&gt;1 — коллекция, 2 — папка, 3 — запрос&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;lMdW&quot;&gt;Главные понятия, которыми оперирует Postman это Collection (коллекция) на верхнем уровне, и Request (запрос) на нижнем. Вся работа начинается с коллекции и сводится к описанию вашего API с помощью запросов. Давайте рассмотрим подробнее всё по порядку.&lt;/p&gt;
  &lt;h4 id=&quot;collection&quot;&gt;Collection&lt;/h4&gt;
  &lt;p id=&quot;XOn9&quot;&gt;Коллекция — отправная точка для нового API. Можно рассматривать коллекцию, как файл проекта. Коллекция объединяет в себе все связанные запросы. Обычно API описывается в одной коллекции, но если вы желаете, то нет никаких ограничений сделать по-другому. Коллекция может иметь свои скрипты и переменные, которые мы рассмотрим позже.&lt;/p&gt;
  &lt;h4 id=&quot;folder&quot;&gt;Folder&lt;/h4&gt;
  &lt;p id=&quot;gDfL&quot;&gt;Папка — используется для объединения запросов в одну группу внутри коллекции. К примеру, вы можете создать папку для первой версии своего API — &amp;quot;v1&amp;quot;, а внутри сгруппировать запросы по смыслу выполняемых действий — &amp;quot;Order &amp;amp; Checkout&amp;quot;, &amp;quot;User profile&amp;quot; и т. п. Всё ограничивается лишь вашей фантазией и потребностями. Папка, как и коллекция может иметь свои скрипты, но не переменные.&lt;/p&gt;
  &lt;h4 id=&quot;request&quot;&gt;Request&lt;/h4&gt;
  &lt;p id=&quot;ttIS&quot;&gt;Запрос — основная составляющая коллекции, то ради чего все и затевалось. Запрос создается в конструкторе. Конструктор запросов это главное пространство, с которым вам придётся работать. Postman умеет выполнять запросы с помощью всех стандартных HTTP методов, все параметры запроса под вашим контролем. Вы с лёгкостью можете поменять или добавить необходимые вам заголовки, cookie, и тело запроса. У запроса есть свои скрипты. Обратите внимание на вкладки &amp;quot;Pre-request Script&amp;quot; и &amp;quot;Tests&amp;quot; среди параметров запроса. Они позволяют добавить скрипты перед выполнением запроса и после. Именно эти две возможности делают Postman мощным инструментом помогающим при разработке и тестировании.&lt;/p&gt;
  &lt;figure id=&quot;mjHa&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/8b7/698/2d3/8b76982d3b64b1eacf778bb2e3dd557b.png&quot; width=&quot;997&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ml9y&quot;&gt;&lt;em&gt;1 — вкладки с запросами, 2 — URL и метод, 3 — параметры запроса, 4 — параметры ответа&lt;/em&gt;&lt;/p&gt;
  &lt;h4 id=&quot;skripty&quot;&gt;Скрипты&lt;/h4&gt;
  &lt;p id=&quot;yPRI&quot;&gt;&amp;quot;Postman Sandbox&amp;quot; это среда исполнения JavaScript доступная при написании &amp;quot;Pre-request Script&amp;quot; и &amp;quot;Tests&amp;quot; скриптов. &amp;quot;Pre-request Script&amp;quot; используется для проведения необходимых операций перед запросом, например, можно сделать запрос к другой системе и использовать результат его выполнения в основном запросе. &amp;quot;Tests&amp;quot; используется для написания тестов, проверки результатов, и при необходимости их сохранения в переменные.&lt;/p&gt;
  &lt;figure id=&quot;pQA8&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/14b/35b/d47/14b35bd47e7a4ee73cd4b9d2fa642cd9.png&quot; width=&quot;889&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;KKTK&quot;&gt;&lt;em&gt;Последовательность выполнения запроса (из оф. документации)&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;ELze&quot;&gt;Помимо скриптов на уровне запроса, мы можем создавать скрипты на уровне папки, и, даже, на уровне коллекции. Они называются также — &amp;quot;Pre-request Script&amp;quot; и &amp;quot;Tests&amp;quot;, но их отличие в том, что они будут выполняться перед каждым и после каждого запроса в папке, или, как вы могли догадаться, во всей коллекции.&lt;/p&gt;
  &lt;figure id=&quot;RTBN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/f1a/c1b/422/f1ac1b422a2fcd9226f70f43ccffbf5f.png&quot; width=&quot;1307&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;6jOC&quot;&gt;&lt;em&gt;Последовательность выполнения запроса со скриптами папок и коллекций (из оф. документации)&lt;/em&gt;&lt;/p&gt;
  &lt;h4 id=&quot;peremennye&quot;&gt;Переменные&lt;/h4&gt;
  &lt;p id=&quot;Rfpb&quot;&gt;Postman имеет несколько пространств и областей видимости для переменных:&lt;/p&gt;
  &lt;ul id=&quot;wbEK&quot;&gt;
    &lt;li id=&quot;WW82&quot;&gt;Глобальные переменные&lt;/li&gt;
    &lt;li id=&quot;DZa1&quot;&gt;Переменные коллекции&lt;/li&gt;
    &lt;li id=&quot;LFcF&quot;&gt;Переменные окружения&lt;/li&gt;
    &lt;li id=&quot;jGSL&quot;&gt;Локальные переменные&lt;/li&gt;
    &lt;li id=&quot;SsCa&quot;&gt;Переменные уровня данных&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;xz3A&quot;&gt;Глобальные переменные и переменные окружения можно создать, если нажать на шестеренку в правом верхнем углу программы. Они существуют отдельно от коллекций. Переменные уровня коллекции создаются непосредственно при редактировании параметров коллекции, а локальные переменные из выполняемых скриптов. Также существуют переменные уровня данных, но они доступны только из Runner, о котором мы поговорим позже.&lt;/p&gt;
  &lt;figure id=&quot;pbkp&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/069/3b2/45b/0693b245b5f7d9defa176ecfa04ee4bb.png&quot; width=&quot;384&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hR71&quot;&gt;&lt;em&gt;Приоритет пространств переменных (из оф. документации)&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;lqg7&quot;&gt;Особенностью переменных в Postman является то, что вы можете вставлять их в конструкторе запроса, в URL, в POST параметры, в Cookie, всюду, используя фигурные скобки в качестве плейсхолдера для подстановки.&lt;/p&gt;
  &lt;figure id=&quot;KgGJ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/089/5ab/874/0895ab874bb1f98c315287f677848391.png&quot; width=&quot;984&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Znif&quot;&gt;&lt;em&gt;{{domain}} и {{slack_incoming_webhook}} — переменные окружения DNS Checker будут заменены на значения во время выполнения запроса&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;syIu&quot;&gt;Из скриптов переменные тоже доступны, но получить их поможет вызов стандартного метода встроенной библиотеки pm:&lt;/p&gt;
  &lt;pre id=&quot;QTvV&quot;&gt;// получить глобальную переменнуюpm.globals.get(&amp;quot;variable_key&amp;quot;);// получить переменную из окруженияpm.environment.get(&amp;quot;variable_key&amp;quot;);// получить переменную из любого пространства согласно приоритетуpm.variables.get(&amp;quot;variable_key&amp;quot;);&lt;/pre&gt;
  &lt;h4 id=&quot;collection-runner&quot;&gt;Collection Runner&lt;/h4&gt;
  &lt;p id=&quot;ibrr&quot;&gt;Предназначен для тестирования и выполнения всех запросов из коллекции или папки, на ваш выбор. При запуске можно указать количество итераций, сколько раз будет запущена папка или коллекция, окружение, а также дополнительный файл с переменными. Стоит упомянуть, что запросы выполняются последовательно, согласно расположению в коллекции и папках. Порядок выполнения можно изменить используя встроенную команду:&lt;/p&gt;
  &lt;pre id=&quot;81B6&quot;&gt;// Следующим выполнится запрос с названием &amp;quot;Create order&amp;quot;,postman.setNextRequest(&amp;#x27;Create order&amp;#x27;);&lt;/pre&gt;
  &lt;p id=&quot;7zbn&quot;&gt;После выполнения всех запросов формируется отчет, который покажет количество успешных и провальных проверок из скриптов &amp;quot;Tests&amp;quot;.&lt;/p&gt;
  &lt;figure id=&quot;GXI9&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/108/6e6/b68/1086e6b68c6a2dd81b72a7b3de4e9db8.png&quot; width=&quot;1151&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;K7nk&quot;&gt;&lt;em&gt;Collection Runner&lt;/em&gt;&lt;/p&gt;
  &lt;h4 id=&quot;console&quot;&gt;Console&lt;/h4&gt;
  &lt;p id=&quot;ywbd&quot;&gt;Пользуйтесь консолью для отладки ваших скриптов, и просмотра дополнительной информации по запросам. Консоль работает, как во время запуска одного запроса, так и во время запуска пакета запросов через Runner. Чтобы её открыть, найдите иконку консоли в нижнем левом углу основного экрана приложения:&lt;/p&gt;
  &lt;figure id=&quot;yESF&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/7c6/cd3/a31/7c6cd3a317347d042152d5d5595c71bc.png&quot; width=&quot;114&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;praktika&quot;&gt;Практика&lt;/h2&gt;
  &lt;p id=&quot;UAuj&quot;&gt;Так как создание коллекций и запросов в конструкторе не должно вызвать затруднений, практическую часть посвятим написанию скриптов, и рассмотрим как создать цепочку запросов с тестами. Перед началом создайте новую коллекцию, назовите её “Habra”, затем создайте новое окружение под названием &amp;quot;Habra.Env&amp;quot;&lt;/p&gt;
  &lt;h3 id=&quot;shag-1&quot;&gt;Шаг 1&lt;/h3&gt;
  &lt;p id=&quot;X4Av&quot;&gt;Создайте новый запрос, в качестве URL укажите &lt;a href=&quot;https://postman-echo.com/get?userId=777&quot; target=&quot;_blank&quot;&gt;https://postman-echo.com/get?userId=777&lt;/a&gt;, а метод оставьте GET. Здесь и далее для простоты и удобства мы будем использовать echo-сервер любезно предоставленный разработчиками Postman. Сохраните запрос в коллекцию &amp;quot;Habra&amp;quot; и назовите “Get user id”, он будет имитировать получение идентификатора пользователя от сервера. Перейдите на вкладку &amp;quot;Tests&amp;quot; и напишите следующий код:&lt;/p&gt;
  &lt;pre id=&quot;7ole&quot;&gt;// Тестируем статус ответа и форматpm.test(&amp;quot;Status is ok, response is json&amp;quot;, function () {    pm.response.to.be.ok; // проверка статуса    pm.response.to.be.json; // проверка формата});try {    // сохраняем userId из json ответа в переменную окружения    pm.environment.set(&amp;quot;userId&amp;quot;, pm.response.json().args.userId);} catch(e) {    // выводим исключение в консоль    console.log(e);}&lt;/pre&gt;
  &lt;p id=&quot;hAKD&quot;&gt;С помощью этого скрипта мы проверили статус и формат ответа, а также сохранили полученный из ответа идентификатор пользователя в переменную окружения для последующего использования в других запросах. Чтобы проверить работу нашего теста, запустите запрос. В панели информации об ответе, во вкладке &amp;quot;Tests&amp;quot; вы должны увидеть зелёный лейбл “PASS”, а рядом надпись “Status is ok, response is json”.&lt;/p&gt;
  &lt;h3 id=&quot;shag-2&quot;&gt;Шаг 2&lt;/h3&gt;
  &lt;p id=&quot;uvOQ&quot;&gt;Теперь давайте попробуем вставить идентификатор нашего пользователя в json запрос. Создайте новый запрос, в качестве URL укажите &lt;a href=&quot;https://postman-echo.com/post&quot; target=&quot;_blank&quot;&gt;https://postman-echo.com/post&lt;/a&gt;, выберите метод POST, установите тип для тела запроса raw — application/json, а в само тело вставьте:&lt;/p&gt;
  &lt;pre id=&quot;pYdD&quot;&gt;{&amp;quot;userId&amp;quot;: {{userId}}, &amp;quot;username&amp;quot;: &amp;quot;Bob&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;MljA&quot;&gt;Сохраните запрос в нашу коллекцию, и назовите &amp;quot;Update username&amp;quot;, он будет запрашивать импровизированную конечную точку для обновления username пользователя. Теперь при вызове запроса вместо {{userId}} система автоматически будет подставлять значение из переменной окружения. Давайте проверим, что это действительно так, и напишем небольшой тест для нашего нового запроса:&lt;/p&gt;
  &lt;pre id=&quot;dnDs&quot;&gt;// тестируем статус ответа и форматpm.test(&amp;quot;Status is ok, response is json&amp;quot;, function () {    pm.response.to.be.ok;    pm.response.to.be.json;});// проверим, что userId из окружения равен userId из ответаpm.test(&amp;quot;userId from env is equal to userId from response&amp;quot;, function () {    pm.expect(parseInt(pm.environment.get(&amp;quot;userId&amp;quot;))).to.equal(        pm.response.json().data.userId    );});&lt;/pre&gt;
  &lt;p id=&quot;HFLU&quot;&gt;В нашем новом тесте мы сравниваем полученный от сервера userId с тем, что хранится у нас в переменной окружения, они должны совпадать. Запустите запрос и убедитесь, что тесты прошли. Хорошо, двигаемся дальше.&lt;/p&gt;
  &lt;h3 id=&quot;shag-3&quot;&gt;Шаг 3&lt;/h3&gt;
  &lt;p id=&quot;3OBX&quot;&gt;Вы могли заметить, что два тестовых скрипта имеют одинаковую проверку формата и статуса:&lt;/p&gt;
  &lt;pre id=&quot;js6h&quot;&gt;pm.test(&amp;quot;Status is ok, response is json&amp;quot;, function () {    pm.response.to.be.ok;    pm.response.to.be.json;});&lt;/pre&gt;
  &lt;p id=&quot;XCs4&quot;&gt;Пока мы не зашли слишком далеко, давайте исправим эту ситуацию и перенесем эти тесты на уровень коллекции. Откройте редактирование нашей коллекции, и перенесите проверку формата и статуса во вкладку &amp;quot;Tests&amp;quot;, а из запросов их можно удалить. Теперь эти проверки будут автоматически вызываться перед скриптами &amp;quot;Tests&amp;quot; для каждого запроса в коллекции. Таким образом мы избавились от копирования данной проверки в каждый запрос.&lt;/p&gt;
  &lt;h3 id=&quot;shag-4&quot;&gt;Шаг 4&lt;/h3&gt;
  &lt;p id=&quot;BIb5&quot;&gt;Мы научились записывать и получать переменные окружения, настало время перейти к чему-то потяжелее. Давайте воспользуемся встроенной библиотекой tv4 (TinyValidator) и попробуем проверить правильность схемы json объекта. Создайте новый запрос, в качестве URL используйте &lt;a href=&quot;https://postman-echo.com/post&quot; target=&quot;_blank&quot;&gt;https://postman-echo.com/post&lt;/a&gt;, установите метод в значение POST, для тела запроса укажите raw — application/json, и вставьте в него:&lt;/p&gt;
  &lt;pre id=&quot;L7ty&quot;&gt;{    &amp;quot;profile&amp;quot; : {        &amp;quot;userId&amp;quot;: {{userId}},        &amp;quot;username&amp;quot;: &amp;quot;Bob&amp;quot;,        &amp;quot;scores&amp;quot;: [1, 2, 3, 4, 5],        &amp;quot;age&amp;quot;: 21,        &amp;quot;rating&amp;quot;: {&amp;quot;min&amp;quot;: 20, &amp;quot;max&amp;quot;: 100}    }}&lt;/pre&gt;
  &lt;p id=&quot;TF8l&quot;&gt;После запуска запроса echo-сервер должен вернуть нам нашу json модель в качестве ответа в поле &amp;quot;data&amp;quot;, таким образом мы имитируем работу реального сервера, который мог бы прислать нам информацию о профиле Боба. Модель готова, напишем тест, проверяющий правильность схемы:&lt;/p&gt;
  &lt;pre id=&quot;neOq&quot;&gt;// получаем профиль из ответаvar profile = pm.response.json().data.profile;// описываем схему моделиvar scheme = {    // указываем тип объекта    &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,    // указываем обязательные свойства    &amp;quot;required&amp;quot;: [&amp;quot;userId&amp;quot;, &amp;quot;username&amp;quot;],    // описываем свойства    &amp;quot;properties&amp;quot;: {        &amp;quot;userId&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},        &amp;quot;username&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},        &amp;quot;age&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},        // описываем массив        &amp;quot;scores&amp;quot;: {            &amp;quot;type&amp;quot;: &amp;quot;array&amp;quot;,            // тип элементов            &amp;quot;items&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}        },        // описываем вложенный объект        &amp;quot;rating&amp;quot;: {            &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,            &amp;quot;properties&amp;quot;: {                &amp;quot;min&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},                &amp;quot;max&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}            }        }    }};pm.test(&amp;#x27;Schema is valid&amp;#x27;, function() {    // валидируем объект profile с помощью правил из scheme    var isValidScheme = tv4.validate(profile, scheme, true, true);    // ожидаем, что результат валидации true    pm.expect(isValidScheme).to.be.true;});&lt;/pre&gt;
  &lt;p id=&quot;ErIH&quot;&gt;Готово, мы провалидировали схему объекта profile. Запустите запрос и убедитесь, что тесты проходят.&lt;/p&gt;
  &lt;h3 id=&quot;shag-5&quot;&gt;Шаг 5&lt;/h3&gt;
  &lt;p id=&quot;DrFt&quot;&gt;У нас получился небольшой путь из 3-х запросов и нескольких тестов. Настало время полностью его протестировать. Но перед этим, давайте внесем небольшую модификацию в наш первый запрос: замените значение “777” в URL на плейсхолдер “{{newUserId}}”, и через интерфейс добавьте в окружение &amp;quot;Habra.Env&amp;quot; переменную “newUserId” со значением “777”. Создайте файл users.json на своём компьютере и поместите туда следующий json массив:&lt;/p&gt;
  &lt;pre id=&quot;y3Py&quot;&gt;[    {&amp;quot;newUserId&amp;quot;: 100},    {&amp;quot;newUserId&amp;quot;: 200},    {&amp;quot;newUserId&amp;quot;: 300},    {&amp;quot;newUserId&amp;quot;: 50000}]&lt;/pre&gt;
  &lt;p id=&quot;jaHr&quot;&gt;Теперь запустим Runner. В качестве &amp;quot;Collection Folder&amp;quot; выберем &amp;quot;Habra&amp;quot;. В качестве &amp;quot;Environment&amp;quot; поставим &amp;quot;Habra.Env&amp;quot;. Количество итераций оставляем 0, а в поле &amp;quot;Data&amp;quot; выбираем наш файл users.json. По этому файлу &amp;quot;Collection Runner&amp;quot; поймет, что ему нужно совершить 4 итерации, и в каждой итерации он заменит значение переменной &amp;quot;newUserId&amp;quot; значением из массива в файле. Если указать количество итераций больше, чем количество элементов в массиве, то все последующие итерации будут происходить с последним значением из массива данных. В нашем случае после 4 итерации значение &amp;quot;newUserId&amp;quot; всегда будет равно 50000. Наш “Data” файл поможет пройти весь наш путь с разными newUserId, и убедиться, что независимо от пользователя все выполняется стабильно.&lt;/p&gt;
  &lt;p id=&quot;5vNa&quot;&gt;Запускаем наши тесты нажатием &amp;quot;Run Habra&amp;quot;. Поздравляем вы успешно создали коллекцию и протестировали наш импровизированный путь с помощью автотестов!&lt;/p&gt;
  &lt;figure id=&quot;yY2p&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/661/4de/c29/6614dec295b8c02c6b6356fb9e6ec00b.png&quot; width=&quot;1151&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;wmay&quot;&gt;&lt;em&gt;Тестирование коллекции &amp;quot;Habra&amp;quot;&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;u3ab&quot;&gt;Теперь вы знаете, как создавать скрипты и вполне можете написать парочку тестов для своего проекта.&lt;/p&gt;
  &lt;p id=&quot;d6kv&quot;&gt;Отдельно хочу отметить, что в реальном проекте мы не держим все запросы в корне коллекции, а стараемся раскладывать их по папкам. Например, в папке &amp;quot;Requests&amp;quot; мы складываем все возможные запросы описывающие наш API, а тесты храним в отдельной папке &amp;quot;Tests&amp;quot;. И когда нам нужно протестировать проект, в &amp;quot;Runner&amp;quot; запускаем только папочку &amp;quot;Tests&amp;quot;.&lt;/p&gt;
  &lt;ul id=&quot;TfGs&quot;&gt;
    &lt;li id=&quot;QwbG&quot;&gt;&lt;a href=&quot;https://github.com/actopolus/postman.habr&quot; target=&quot;_blank&quot;&gt;Коллекция, окружение и данные из примера&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;polezno-znat&quot;&gt;Полезно знать&lt;/h2&gt;
  &lt;p id=&quot;nA4E&quot;&gt;В завершении приведем основные команды, которые вам могут понадобиться во время написания скриптов. Для лучшего усвоения, попробуйте поиграться с ними самостоятельно.&lt;/p&gt;
  &lt;h4 id=&quot;ustanovka-i-poluchenie-peremennyh&quot;&gt;Установка и получение переменных&lt;/h4&gt;
  &lt;pre id=&quot;R5QM&quot;&gt;// глобальные переменныеpm.globals.set(“key”, “value”);pm.globals.get(“key”);// переменные окруженияpm.environment.set(“key”, “value”);pm.environment.get(“key”);// локальные переменныеpm.variables.set(“key”, “value”);pm.variables.get(“key”); // если нет локальной, будет искать на уровне выше&lt;/pre&gt;
  &lt;h4 id=&quot;testirovanie-ili-asserts&quot;&gt;Тестирование или asserts&lt;/h4&gt;
  &lt;pre id=&quot;1SUr&quot;&gt;// с использованием анонимной функции и специальных assert конструкцийpm.test(“Название теста”, function () {    pm.response.to.be.success;    pm.expect(“value”).to.be.true;    pm.expect(“other”).to.equal(“other”);});// с использованием простого условия и массива teststests[“Название теста”] = (“a” != “b”);tests[“Название теста 2”] = true;&lt;/pre&gt;
  &lt;h4 id=&quot;sozdanie-zaprosov&quot;&gt;Создание запросов&lt;/h4&gt;
  &lt;pre id=&quot;M7sy&quot;&gt;// пример get запросаpm.sendRequest(“https://postman-echo.com/get”, function (err, res) {    console.log(err);    console.log(res);});// пример post запросаlet data = {    url: “https://postman-echo.com/post”,    method: “POST”,    body: { mode: “raw”, raw: JSON.stringify({ key: “value” })}};pm.sendRequest(data, function (err, res) {    console.log(err);    console.log(res);});&lt;/pre&gt;
  &lt;h4 id=&quot;poluchenie-otveta-dlya-osnovnogo-zaprosa&quot;&gt;Получение ответа для основного запроса&lt;/h4&gt;
  &lt;pre id=&quot;CzwQ&quot;&gt;pm.response.json(); // в виде jsonpm.response.text(); // в виде строкиresponseBody; // в виде строки&lt;/pre&gt;
  &lt;p id=&quot;Ffbx&quot;&gt;Ответ доступен только во вкладке “Tests”&lt;/p&gt;
  &lt;h4 id=&quot;rabota-so-vstroennymi-bibliotekami&quot;&gt;Работа со встроенными библиотеками&lt;/h4&gt;
  &lt;p id=&quot;qnvV&quot;&gt;Документация регламентирует наличие некоторого количества встроенных библиотек, среди которых — tv4 для валидации json, xml2js конвертер xml в json, crypto-js для работы с шифрованием, atob, btoa и др.&lt;/p&gt;
  &lt;pre id=&quot;gRmM&quot;&gt;// подключение xml2jsvar xml2js = require(“xml2js”);// преобразование простого xml в json объектxml2js.parseString(&amp;quot;&amp;lt;root&amp;gt;Hello xml2js!&amp;lt;/root&amp;gt;&amp;quot;, function(err, res) {    console.log(res);});&lt;/pre&gt;
  &lt;p id=&quot;4OPv&quot;&gt;Некоторые из библиотек, например, как tv4 не требуют прямого подключения через require и доступны по имени сразу.&lt;/p&gt;
  &lt;h4 id=&quot;poluchenie-informacii-o-tekuschem-skripte&quot;&gt;Получение информации о текущем скрипте&lt;/h4&gt;
  &lt;pre id=&quot;zG7P&quot;&gt;pm.info.eventName; // вернет test или prerequest в зависимости от контекстаpm.info.iteration; // текущая итерация в Runnerpm.info.iterationCount; // общее количество итерацийpm.info.requestName; // название текущего запросаpm.info.requestId; // внутренний идентификатор запроса&lt;/pre&gt;
  &lt;h4 id=&quot;upravlenie-posledovatelnostyu-zaprosov-iz-skripta&quot;&gt;Управление последовательностью запросов из скрипта&lt;/h4&gt;
  &lt;p id=&quot;PBsZ&quot;&gt;Стоит отметить, что данный метод работает только в режиме запуска всех скриптов.&lt;/p&gt;
  &lt;pre id=&quot;LzzC&quot;&gt;// установить следующий запросpostman.setNextRequest(“Название запроса”); // по названиюpostman.setNextRequest(ID); // по идентификатору// остановить выполнение запросовpostman.setNextRequest(null);&lt;/pre&gt;
  &lt;p id=&quot;t2L0&quot;&gt;После перехода на следующий запрос Postman возвращается к линейному последовательному выполнению запросов.&lt;/p&gt;
  &lt;h4 id=&quot;sozdanie-globalnogo-helpera&quot;&gt;Создание глобального хелпера&lt;/h4&gt;
  &lt;p id=&quot;pPqi&quot;&gt;В некоторых случаях вам захочется создать функции, которые должны быть доступны во всех запросах. Для этого в первом запросе в секции “Pre-request Script” напишите следующий код:&lt;/p&gt;
  &lt;pre id=&quot;k2D8&quot;&gt;// создаем и сохраняем хелпер для глобального использованияpm.environment.set(&amp;quot;pmHelper&amp;quot;, function pmHelper() {    let helpers = {};    helpers.usefulMethod = function() {        console.log(“It is helper, bro!”);    };    return helpers;} + &amp;#x27;; pmHelper();&amp;#x27;);&lt;/pre&gt;
  &lt;p id=&quot;dAvr&quot;&gt;А в последующих скриптах пользуемся им так:&lt;/p&gt;
  &lt;pre id=&quot;vG7v&quot;&gt;// получаем объектvar pmHelper = eval(pm.environment.get(&amp;quot;pmHelper&amp;quot;));// вызываем наш методpmHelper.usefulMethod();&lt;/pre&gt;
  &lt;p id=&quot;US0D&quot;&gt;Это лишь небольшой список полезных команд. Возможности скриптов гораздо шире, чем можно осветить в одной статье. В Postman есть хорошие &amp;quot;Templates&amp;quot;, которые можно найти при создании новой коллекции. Не стесняйтесь подглядывать и изучать их реализацию. А официальная документация содержит ответы на большинство вопросов.&lt;/p&gt;
  &lt;ul id=&quot;1siR&quot;&gt;
    &lt;li id=&quot;jS5d&quot;&gt;&lt;a href=&quot;https://www.getpostman.com/&quot; target=&quot;_blank&quot;&gt;Официальный сайт&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;zrX4&quot;&gt;&lt;a href=&quot;https://www.getpostman.com/docs/&quot; target=&quot;_blank&quot;&gt;Документация по Postman &lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;ryjY&quot;&gt;&lt;a href=&quot;https://www.getpostman.com/docs/postman/scripts/postman_sandbox_api_reference&quot; target=&quot;_blank&quot;&gt;Список встроенных библиотек&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;zaklyuchenie&quot;&gt;Заключение&lt;/h2&gt;
  &lt;p id=&quot;GY6P&quot;&gt;Основные плюсы, которые подтолкнули нас к использованию Postman в своём проекте:&lt;/p&gt;
  &lt;ul id=&quot;bBDT&quot;&gt;
    &lt;li id=&quot;5EMY&quot;&gt;Наглядность – все запросы всегда под рукой, мануальное тестирование во время разработки становится легче&lt;/li&gt;
    &lt;li id=&quot;oZmb&quot;&gt;Быстрый старт – вовлечение нового игрока в команду, будь то программист или тестировщик, проходит легко и быстро&lt;/li&gt;
    &lt;li id=&quot;xsiq&quot;&gt;Тесты – возможность писать тесты для запросов, а потом быстро составлять из них, как из пазлов, различные варианты и пути жизни приложения&lt;/li&gt;
    &lt;li id=&quot;J8dd&quot;&gt;Поддержка CI — возможность интегрировать тесты в CI с помощью newman (об этом будет отдельная статья)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;rS0H&quot;&gt;Среди минусов можно выделить:&lt;/p&gt;
  &lt;ul id=&quot;VKpA&quot;&gt;
    &lt;li id=&quot;CkOc&quot;&gt;Редактирование коллекции привязано к Postman, т. е. для изменений потребуется сделать импорт, отредактировать, а затем сделать экспорт в репозиторий проекта&lt;/li&gt;
    &lt;li id=&quot;1zxb&quot;&gt;Так как коллекция лежит в одном большом json файле, Review изменений практически невозможно&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;822z&quot;&gt;У каждого проекта свои подходы и взгляды на тестирование и разработку. Мы увидели для себя больше плюсов, чем минусов, и поэтому решили использовать этот мощный инструмент, как для тестирования, так и для описания запросов к API нашего проекта. И по своему опыту можем сказать, даже, если вы не будете использовать средства тестирования, которые предоставляет Postman, то иметь описание запросов в виде коллекции будет весьма полезно. Коллекции Postman это живая, интерактивная документация к вашему API, которая сэкономит множество времени, и в разы ускорит разработку, отладку и тестирование!&lt;/p&gt;
  &lt;p id=&quot;vi1P&quot;&gt;&lt;u&gt;P.S.:&lt;/u&gt;&lt;br /&gt;Основной функционал Postman бесплатен и удовлетворяет ежедневным нуждам, но есть некоторые инструменты с рядом ограничений в бесплатной версии:&lt;/p&gt;
  &lt;ul id=&quot;dfBm&quot;&gt;
    &lt;li id=&quot;Hlew&quot;&gt;Postman API – позволяет получать доступ к данным вашего аккаунта, добавлять, удалять и обновлять коллекции, запросы, и другую информацию программно, напрямую через API. Вы можете обратиться к нему 1000 раз в месяц.&lt;/li&gt;
    &lt;li id=&quot;73gj&quot;&gt;Mock сервер – позволяет развернуть заглушки для вашего API на серверах разработчиков Postman. Доступно 1000 запросов в месяц.&lt;/li&gt;
    &lt;li id=&quot;ix04&quot;&gt;Api Monitoring – позволяет создавать коллекции для мониторинга и запуска их по расписанию с серверов разработчика Postman. Система мониторинга сделает для вас не больше 1000 запросов в месяц&lt;/li&gt;
    &lt;li id=&quot;55fb&quot;&gt;Api Documentation – позволяет публиковать автоматически сгенерированную документацию на серверах приложения Postman. Ограничение 1000 просмотров в месяц&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;4ghf&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/zfrQtU8eCEo?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;H3b6&quot;&gt;&lt;/p&gt;
  &lt;h1 id=&quot;2Ixi&quot;&gt;Как тестировать методы REST API&lt;/h1&gt;
  &lt;p id=&quot;5lkX&quot;&gt;Когда ручного тестировщика впервые просишь проверить метод REST API, того охватывает паника: «Как это делать? Я вообще почти ничего не знаю про API. Что делать? Как это тестировать?»&lt;/p&gt;
  &lt;p id=&quot;e8Cs&quot;&gt;Спокойно. Без паники =) Я уже рассказывала на простом языке, &lt;a href=&quot;https://habr.com/ru/post/464261/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;что такое API&lt;/u&gt;&lt;/a&gt;. А сегодня я расскажу о том, как его тестировать. На самом деле почти также, как GUI: в первую очередь это тест-дизайн и придумывание проверок, а потом уже всякие API-штучки. Но и про них не стоит забывать.&lt;/p&gt;
  &lt;p id=&quot;zHHH&quot;&gt;Я дам вам чек-лист, к которому вы сможете обращаться потом — «так, это проверил, и это, и это. А вот это забыл, пойду посмотрю!». А потом мы обсудим каждый пункт — зачем это проверять и как.&lt;/p&gt;
  &lt;p id=&quot;WF2W&quot;&gt;После теории будет практика! Для неё возьмем метод &lt;a href=&quot;https://okiseleva.blogspot.com/2022/11/doregister-soap-rest-users.html&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;doRegister&lt;/u&gt;&lt;/a&gt; системы Users — он находится в открытом доступе, можете дергать по ходу чтения и проверять =)&lt;/p&gt;
  &lt;h2 id=&quot;G89M&quot;&gt;Чек-лист проверок&lt;/h2&gt;
  &lt;p id=&quot;vUtZ&quot;&gt;Общий чек-лист:&lt;/p&gt;
  &lt;ol id=&quot;BMTO&quot;&gt;
    &lt;li id=&quot;LCpD&quot;&gt;Правильное тело (пример)&lt;/li&gt;
    &lt;li id=&quot;Q6Vn&quot;&gt;Бизнес-логика: позитив, негатив&lt;/li&gt;
    &lt;li id=&quot;yBWZ&quot;&gt;Различные параметры (обязательность, работа параметров)&lt;/li&gt;
    &lt;li id=&quot;FYmb&quot;&gt;Перестановка мест слагаемых (заголовки, тело)&lt;/li&gt;
    &lt;li id=&quot;dun2&quot;&gt;Регистрозависимость (заголовки, тело)&lt;/li&gt;
    &lt;li id=&quot;D8v7&quot;&gt;Ошибки: не well formed xml / json&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;wixi&quot;&gt;Где искать параметры:&lt;/p&gt;
  &lt;ul id=&quot;OaFK&quot;&gt;
    &lt;li id=&quot;Rvev&quot;&gt;В URL&lt;/li&gt;
    &lt;li id=&quot;HgkV&quot;&gt;В заголовках&lt;/li&gt;
    &lt;li id=&quot;4pWr&quot;&gt;В теле запроса&lt;/li&gt;
    &lt;li id=&quot;ZRv1&quot;&gt;Комбинация&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;8KPj&quot;&gt;Тестирование параметров:&lt;/p&gt;
  &lt;ol id=&quot;D9cP&quot;&gt;
    &lt;li id=&quot;7XU9&quot;&gt;Правильный параметр (из примера)&lt;/li&gt;
    &lt;li id=&quot;XY7m&quot;&gt;Обязательность (что, если параметр не указать?)&lt;/li&gt;
    &lt;li id=&quot;zRg2&quot;&gt;Бизнес-логика (тест-дизайн)&lt;/li&gt;
    &lt;li id=&quot;9Hmf&quot;&gt;Регистрозависимость (если параметр текстовый)&lt;/li&gt;
    &lt;li id=&quot;cvxu&quot;&gt;Перестановка местами&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;2W0R&quot;&gt;То есть берём REST-часть и обычную, применяем тест-дизайн, словно это параметр в графическом интерфейсе.&lt;/p&gt;
  &lt;p id=&quot;Vhco&quot;&gt;Тестирование заголовков:&lt;/p&gt;
  &lt;ul id=&quot;C9vm&quot;&gt;
    &lt;li id=&quot;Gehj&quot;&gt;Заголовки из документации работают (в целом)&lt;/li&gt;
    &lt;li id=&quot;9bR7&quot;&gt;А если какой-то не передать? (обязательность)&lt;/li&gt;
    &lt;li id=&quot;9AZu&quot;&gt;А если передать, но неправильно? (текст ошибки)&lt;/li&gt;
    &lt;li id=&quot;Lo1b&quot;&gt;Позитивные тесты по доке&lt;/li&gt;
    &lt;li id=&quot;Xtlo&quot;&gt;Регистронезависимость заголовков&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;upmJ&quot;&gt;Что смотрим в ответе:&lt;/p&gt;
  &lt;ul id=&quot;NPhO&quot;&gt;
    &lt;li id=&quot;P834&quot;&gt;Status Code&lt;/li&gt;
    &lt;li id=&quot;C64d&quot;&gt;Body&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;GQtF&quot;&gt;В теле смотрим:&lt;/p&gt;
  &lt;ol id=&quot;xrh7&quot;&gt;
    &lt;li id=&quot;DHrP&quot;&gt;Какие поля вернулись в ответе?&lt;/li&gt;
    &lt;li id=&quot;rNMe&quot;&gt;Значения в полях&lt;/li&gt;
    &lt;li id=&quot;vl7s&quot;&gt;Текст ошибок&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;PRvy&quot;&gt;Поля в ответе нужно:&lt;/p&gt;
  &lt;ul id=&quot;Ii95&quot;&gt;
    &lt;li id=&quot;jW1P&quot;&gt;сравнить с ТЗ&lt;/li&gt;
    &lt;li id=&quot;1ZJ6&quot;&gt;сравнить между собой SOAP \ REST&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;FZA0&quot;&gt;Кратко прошлись, теперь разберемся в деталях и с примерами.&lt;/p&gt;
  &lt;h3 id=&quot;BTVz&quot;&gt;Содержание&lt;/h3&gt;
  &lt;ul id=&quot;lETr&quot;&gt;
    &lt;li id=&quot;Aw20&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#positive_or_negative&quot; target=&quot;_blank&quot;&gt;Позитив или негатив?&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;OJbv&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#testing_order&quot; target=&quot;_blank&quot;&gt;В каком порядке тестируем&lt;/a&gt;&lt;/li&gt;
    &lt;ol id=&quot;xRan&quot;&gt;
      &lt;li id=&quot;5Coa&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#examples&quot; target=&quot;_blank&quot;&gt;Примеры&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;tioS&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#root_scenario&quot; target=&quot;_blank&quot;&gt;Основной позитивный сценарий&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;OdJO&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#alternative_scenario&quot; target=&quot;_blank&quot;&gt;Альтернативные сценарии/a&amp;gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;vEgn&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#negative_scenario&quot; target=&quot;_blank&quot;&gt;Негативные сценарии&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;c3mM&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#params_in_req&quot; target=&quot;_blank&quot;&gt;Параметры запроса&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;e6cv&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#other_tests&quot; target=&quot;_blank&quot;&gt;Остальные тесты&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
    &lt;li id=&quot;UVLc&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#tests_in_request&quot; target=&quot;_blank&quot;&gt;Что тестируем в запросе&lt;/a&gt;&lt;/li&gt;
    &lt;ol id=&quot;Fo0K&quot;&gt;
      &lt;li id=&quot;iA0t&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#request_headers&quot; target=&quot;_blank&quot;&gt;Заголовки (Headers)&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;DCev&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#request_body&quot; target=&quot;_blank&quot;&gt;Тело запроса (body)&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;i2T1&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#url&quot; target=&quot;_blank&quot;&gt;URL&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;t8aZ&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#type&quot; target=&quot;_blank&quot;&gt;Тип метода&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
    &lt;li id=&quot;IGCy&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#tests_in_response&quot; target=&quot;_blank&quot;&gt;Что тестируем в ответе&lt;/a&gt;&lt;/li&gt;
    &lt;ol id=&quot;oxKh&quot;&gt;
      &lt;li id=&quot;FQLc&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#response_body&quot; target=&quot;_blank&quot;&gt;Тело ответа&lt;/a&gt;&lt;/li&gt;
      &lt;li id=&quot;kGUm&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#status_code&quot; target=&quot;_blank&quot;&gt;Статус-коды&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
    &lt;li id=&quot;UG98&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#checklist_doRegister&quot; target=&quot;_blank&quot;&gt;Итоговый чек-лист проверки doRegister&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;u1lI&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/704090/#itogo&quot; target=&quot;_blank&quot;&gt;Вывод&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;ftsB&quot;&gt;Позитив или негатив?&lt;/h2&gt;
  &lt;p id=&quot;AllK&quot;&gt;Я учу начинающих тестировщиков так: ВСЕГДА сначала позитивное тестирование, а потом негативное. Иначе вы успеете проверить всякий треш, а с нормальными данными система работать не будет.&lt;/p&gt;
  &lt;p id=&quot;t64N&quot;&gt;Однако в случае тестирования интеграции негатив может оказаться приоритетнее. На одном из рабочих проектов обсуждала это с архитектором, который разрабатывает системы для интеграции — как заказное ПО, так и общедоступное. Он учил меня так:&lt;/p&gt;
  &lt;blockquote id=&quot;xhM8&quot;&gt;Сначала надо проверить негатив. Потому что разработчики продукта, которые подключают наше API, всегда будут напарываться на грабли. Не прочитали документацию / прочитали криво — получили ошибку.И нужно, чтобы по сообщению об ошибке они поняли:— Что они сделали не так— Как это исправитьЭто нужно для того, чтобы уменьшить количество обращений в тех. поддержку.Так что проверьте сначала всякие извращения, а потом, пока разработчик чинит найденные баги, сидите со своими позитивными тестами и позитивными сценариями.&lt;/blockquote&gt;
  &lt;p id=&quot;p2p4&quot;&gt;В целом, есть логика в его словах. Ну и плюс всё зависит от времени, если вам позитивные тесты погонять займет полчасика, то проще начать с них. А если там куча сценариев + обязательные автотесты часа на 4, то можно сначала погонять руками, выдать пачку замечаний и сидеть спокойно писать свои тесты.&lt;/p&gt;
  &lt;p id=&quot;IilY&quot;&gt;Обсудите со своими разработчиками, как им будет удобнее — чтобы вы сначала потыкали “на слом” и прислали очевидные баги, или вдумчиво проверили всё и прислали результат одним файлом. Как им удобнее, так и делайте.&lt;/p&gt;
  &lt;p id=&quot;oLR5&quot;&gt;Но лично я всё же считаю, что как минимум основной сценарий позитивный проверить надо. И желательно пару ответвлений от него.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;N653&quot;&gt;В каком порядке тестируем&lt;/h2&gt;
  &lt;h3 id=&quot;cnAw&quot;&gt;1. Примеры в ТЗ&lt;/h3&gt;
  &lt;p id=&quot;TZfo&quot;&gt;Самое простое, что можно сделать — дернуть пример из документации, чтобы посмотреть, как метод вообще работает. А потом уже писать обвязку в коде.&lt;/p&gt;
  &lt;p id=&quot;3bCo&quot;&gt;Это пойдут делать тестировщики, получив от вас новый функционал. И это же сделает разработчик интеграции / другой пользователь API.&lt;/p&gt;
  &lt;p id=&quot;qSPg&quot;&gt;Отсюда вытекают следующие выводы:&lt;/p&gt;
  &lt;p id=&quot;0fiC&quot;&gt;а) Примеры в документации должны быть! Причем желательно не один, а на каждый интересный кейс. Чтобы на него точно обратили внимание!&lt;/p&gt;
  &lt;p id=&quot;11yk&quot;&gt;б) Примеры тестируем в первую очередь, потому что именно их дернут первыми. И потом будут делать по аналогии.&lt;/p&gt;
  &lt;p id=&quot;VWBW&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;t5zs&quot;&gt;В Users есть только один пример:&lt;/p&gt;
  &lt;pre id=&quot;klVs&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;vMA7&quot;&gt;Его и попробуем отправить!&lt;/p&gt;
  &lt;ul id=&quot;WVGZ&quot;&gt;
    &lt;li id=&quot;Gs4s&quot;&gt;Тип запроса — POST&lt;/li&gt;
    &lt;li id=&quot;Xg0O&quot;&gt;URL — &lt;a href=&quot;http://users.bugred.ru/tasks/rest/doregister&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;http://users.bugred.ru/tasks/rest/doregister&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;aAYX&quot;&gt;Тело — из примера&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;bqgM&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/5a2/404/9de/5a24049deb32893af88619d9837ca8e3.png&quot; width=&quot;940&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;fzQn&quot;&gt;Упс, ошибочка… Читаем её внимательно:&lt;/p&gt;
  &lt;pre id=&quot;6hVC&quot;&gt;&amp;quot; email milli@mail.ru уже есть в базе&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;0Kuz&quot;&gt;В целом логично, раз метод создает нового пользователя, может быть ограничение уникальности. Смотрим в ТЗ, и правда:&lt;/p&gt;
  &lt;blockquote id=&quot;PTnb&quot;&gt;Имя и емейл должны быть уникальными&lt;/blockquote&gt;
  &lt;p id=&quot;MGwl&quot;&gt;Значит, метод не идемпотентный… Нельзя просто взять пример из ТЗ и отправить не глядя.&lt;/p&gt;
  &lt;blockquote id=&quot;5Kky&quot;&gt;&lt;em&gt;&lt;strong&gt;Справка&lt;/strong&gt;Метод HTTP является идемпотентным, если повторный идентичный запрос, сделанный один или несколько раз подряд, имеет один и тот же эффект, не изменяющий состояние сервера. Корректно реализованные методы GET, HEAD, PUT и DELETE идемпотентны, но не метод POST. © &lt;a href=&quot;https://developer.mozilla.org/ru/docs/Glossary/Idempotent&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;developer.mozilla.org&lt;/u&gt;&lt;/a&gt;&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;puf1&quot;&gt;Нужно взять пример и отредактировать его так, чтобы данные стали уникальными. Можно от руки дописать несколько циферок:&lt;/p&gt;
  &lt;pre id=&quot;PZba&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli5678@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька5678&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;nBTW&quot;&gt;А можно использовать функционал Postman, который позволяет указать рандомные значения — &lt;a href=&quot;https://learning.postman.com/docs/writing-scripts/script-references/variables-list/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;динамические переменные&lt;/u&gt;&lt;/a&gt;. Пожалуй, мне хватит $randomInt. Но так как я отправляю запрос в JSON-формате, то надо обернуть переменную в фигурные скобки, иначе постман считает её как простой текст:&lt;/p&gt;
  &lt;pre id=&quot;N37x&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli{{$randomInt}}@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;6Y5f&quot;&gt;Сработало!&lt;/p&gt;
  &lt;figure id=&quot;R1Ej&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/29d/e36/279/29de36279edff24ac8579d79f7cbc606.png&quot; width=&quot;1032&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;irQs&quot;&gt;&lt;strong&gt;См также:&lt;/strong&gt; &lt;a href=&quot;https://okiseleva.blogspot.com/2022/11/postman.html&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;Как понять, что мы отправляли, какую переменную?&lt;/u&gt;&lt;/a&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;mLGK&quot;&gt;Пример проверили, отлично. Он рабочий, но не идемпотентный, так что его нужно скорректировать под себя. Документация НЕ неправильная, запрос рабочий, если его прогонять на пустой базе в первый раз.&lt;/p&gt;
  &lt;p id=&quot;LPd4&quot;&gt;Однако пользователи бывают разные. Они вполне могут скопипастить пример, отправить его, получить ошибку и прибежать в поддержку ругаться, не читая сообщение об ошибке — у вас плохой пример, он не работает.&lt;/p&gt;
  &lt;p id=&quot;lLtG&quot;&gt;И чем больше у вас пользователей, тем больше таких вопросов будет. Заводить ли тут баг на правку документации? Можно предложить дописать в ТЗ как-то так:&lt;/p&gt;
  &lt;blockquote id=&quot;0c28&quot;&gt;Запрос (для проверки запроса исправьте имя пользователя и email, чтобы они были уникальными): ...&lt;/blockquote&gt;
  &lt;p id=&quot;AhNY&quot;&gt;То есть заранее подсказываем, что надо изменить, чтобы запрос сработал AS IS. Можно было бы и пример с рандомными переменными постмана дать, но тут надо понимать, что через постман его будут дергать тестировщики и аналитики со стороны заказчика.&lt;/p&gt;
  &lt;p id=&quot;zGOs&quot;&gt;Разработчики же должны написать код, используя ваш пример. А они тоже любят копипастить))) И если дать пример, заточенный под постман, то к вам снова придут с вопросом, почему ваш пример не работает, но уже в коде. И тут опять или писать около примера, что “$randomInt — переменная Postman, она тут для того-то”, или всё же примеры оставить в покое.&lt;/p&gt;
  &lt;p id=&quot;p6k9&quot;&gt;Я не вижу особой проблемы в текущем описании, это не повод ставить баг на документацию. Пример нормальный и рабочий. А если принесет головную боль поддержке, тогда и замените.&lt;/p&gt;
  &lt;p id=&quot;ADD8&quot;&gt;В нашей доке всего 1 пример. Если бы их было больше, надо было бы вызвать все. Именно на примерах пользователи учатся работать с системой. Дернули, получили такой же ответ, изучили его, осознали, запомнили =)&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;q0bQ&quot;&gt;2. Основной позитивный сценарий&lt;/h3&gt;
  &lt;p id=&quot;xdxu&quot;&gt;Чтобы настраивать интеграцию, разработчику той стороны нужен работающий сценарий. Самый основной, все ответвления можно отладить позже.&lt;/p&gt;
  &lt;p id=&quot;yoDp&quot;&gt;В идеале он берет этот сценарий из примера. Если примеров нет, будет дергать метод наобум, как он считает правильным. Знаете, как с новым девайсом — сначала попробовал сам, если не получилось, пошел читать инструкцию.&lt;/p&gt;
  &lt;p id=&quot;8Awo&quot;&gt;Тем не менее у разработчика есть основной позитивный сценарий его системы, его он и будет проверять. И тестировщик должен проверить его в первую очередь.&lt;/p&gt;
  &lt;p id=&quot;29Ql&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;EGtp&quot;&gt;А у нас есть пример, так что основной позитивный сценарий мы уже почти проверили!&lt;/p&gt;
  &lt;p id=&quot;EXjk&quot;&gt;Почему “почти”? Мы проверили, что система вернула в ответе «успешно создалась Машенька562», но точно ли она создалась? Может быть, разработчик сделал заглушку и пока метод в разработке, он всегда возвращает ответ в стиле “успешный успех”, ничего при этом не делая.&lt;/p&gt;
  &lt;p id=&quot;VXhd&quot;&gt;Так что идем и проверяем, есть ли наша Машенька в GUI — &lt;a href=&quot;http://users.bugred.ru/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;http://users.bugred.ru/&lt;/u&gt;&lt;/a&gt;. Ищем поиском — есть!&lt;/p&gt;
  &lt;figure id=&quot;Lrmp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/7e0/bf9/706/7e0bf97063313c4749d6a4b1a784047c.png&quot; width=&quot;1501&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;uYAk&quot;&gt;Проверяем все поля:&lt;/p&gt;
  &lt;ul id=&quot;86kU&quot;&gt;
    &lt;li id=&quot;op3r&quot;&gt;Емейл правильный, какой мы отправляли.&lt;/li&gt;
    &lt;li id=&quot;oVjk&quot;&gt;Автор «rest», что логично.&lt;/li&gt;
    &lt;li id=&quot;gvql&quot;&gt;Дата изменения — сегодня, что тоже правильно.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;feCa&quot;&gt;Значит, пользователь правда создан! Хотя постойте… Я же выполняла не метод CreateUser, а doRegister. Его основная цель — не создать карточку, а зарегистрировать пользователя в системе. Просто при регистрации карточка автоматом создается, поэтому её тоже зацепили проверкой.&lt;/p&gt;
  &lt;p id=&quot;O5oC&quot;&gt;А как проверить, что регистрация прошла успешно? Правильно, попробовать авторизоваться!&lt;/p&gt;
  &lt;p id=&quot;roln&quot;&gt;Нажимаем «Войти» и вводим наши данные: &lt;a href=&quot;mailto:milli754@mail.ru&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;milli754@mail.ru&lt;/u&gt;&lt;/a&gt; / 1&lt;/p&gt;
  &lt;figure id=&quot;VBrI&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4af/cad/232/4afcad232ec88377df19fdc16a70c3f2.png&quot; width=&quot;1105&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;UMH7&quot;&gt;Вошли! Ура, значит, регистрация правда сработала. Вот теперь мы закончили с основным позитивным сценарием.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;kX8I&quot;&gt;3. Альтернативные сценарии&lt;/h3&gt;
  &lt;p id=&quot;QOti&quot;&gt;На самом деле если в ТЗ нет отдельно выделенного сценария использования, то можно объединить пункты “альтернативные сценарии” и “негативное тестирование”, потому что по факту после базового теста мы:&lt;/p&gt;
  &lt;ol id=&quot;Aumg&quot;&gt;
    &lt;li id=&quot;rM9E&quot;&gt;Читаем каждое предложение из ТЗ, «Особенности использования» или как этот раздел у вас называется&lt;/li&gt;
    &lt;li id=&quot;eU3R&quot;&gt;Продумываем, как его проверить: как позитивно, так и негативно.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;66fn&quot;&gt;Но давайте для чистоты эксперимента попробуем разнести эти пункты отдельно. Тогда в альтернативы попадают все дополнительные условия, которые накладываются на посылаемые или возвращаемые данные.&lt;/p&gt;
  &lt;p id=&quot;k0iZ&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;avDs&quot;&gt;Читаем особенности использования:&lt;/p&gt;
  &lt;blockquote id=&quot;LGu5&quot;&gt;Пользователь создается и появляется в системе.&lt;/blockquote&gt;
  &lt;p id=&quot;WUng&quot;&gt;Это мы уже проверили. Дальше:&lt;/p&gt;
  &lt;blockquote id=&quot;r3kG&quot;&gt;Автор у него всегда будет «SOAP / REST», изменять его можно только через соответствующий-метод.&lt;/blockquote&gt;
  &lt;p id=&quot;tFAJ&quot;&gt;Автора тоже проверили, но только вот в ТЗ он указан капсом, а по факту создается в нижнем регистре. Это уже небольшой баг, скорее всего документации, так как некритично и проще доку обновить. Сделали заметочку / сами исправили доку, если есть доступ.&lt;/p&gt;
  &lt;p id=&quot;lf3N&quot;&gt;А дальше видим, что изменять только только через соответствующий метод. Ага, то есть если создали через REST, менять можно тоже только через REST, через SOAP нельзя. И наоборот. Это и проверим.&lt;/p&gt;
  &lt;p id=&quot;38nI&quot;&gt;Для начала под Машенькой в ГУИ посмотрим, есть ли возможность отредактировать собственную карточку — нету. Ок. Открываем в SOAP Ui WSDL проекта — &lt;a href=&quot;http://users.bugred.ru/tasks/soap/WrapperSoapServer.php?wsdl&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;http://users.bugred.ru/tasks/soap/WrapperSoapServer.php?wsdl&lt;/u&gt;&lt;/a&gt;, и смотрим, каким методом можно вносить изменения.&lt;/p&gt;
  &lt;p id=&quot;ZOmQ&quot;&gt;Нам вполне подойдет UpdateUserOneField, он обновляет одно любое поле пользователя. А как понять, какие поля есть? Покопаться в документации. В Users описаны не все методы, но есть описание &lt;a href=&quot;https://testbase.atlassian.net/wiki/spaces/USERS/pages/871924071/CreateUser&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;CreateUser&lt;/u&gt;&lt;/a&gt;, где можно взять названия полей. Допустим, хочу обновить кличку кошки — cat. Получается запрос:&lt;/p&gt;
  &lt;pre id=&quot;zxxV&quot;&gt;&amp;lt;soapenv:Envelope xmlns:soapenv=&amp;quot;http://schemas.xmlsoap.org/soap/envelope/&amp;quot; xmlns:wrap=&amp;quot;http://foo.bar/wrappersoapserver&amp;quot;&amp;gt;   &amp;lt;soapenv:Header/&amp;gt;   &amp;lt;soapenv:Body&amp;gt;      &amp;lt;wrap:UpdateUserOneField&amp;gt;         &amp;lt;email&amp;gt;milli754@mail.ru&amp;lt;/email&amp;gt;         &amp;lt;field&amp;gt;cat&amp;lt;/field&amp;gt;         &amp;lt;value&amp;gt;Еночка&amp;lt;/value&amp;gt;      &amp;lt;/wrap:UpdateUserOneField&amp;gt;   &amp;lt;/soapenv:Body&amp;gt;&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;XTue&quot;&gt;Отправляем, хммммм:&lt;/p&gt;
  &lt;pre id=&quot;8AnZ&quot;&gt;Поле cat успешно изменено на Еночка у пользователя с email milli754@mail.ru&lt;/pre&gt;
  &lt;p id=&quot;5kml&quot;&gt;Проверяем в интерфейсе, находим карточку пользователя и жмем “Просмотр” &lt;em&gt;(прямую ссылку давать бесполезно, база дропается каждую ночь, тут только самому создать и посмотреть)&lt;/em&gt;. Значение обновилось:&lt;/p&gt;
  &lt;figure id=&quot;X24k&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b5a/be2/12a/b5abe212adcdf28ab1e49fa3aab3a8b8.png&quot; width=&quot;1085&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;coVY&quot;&gt;Значит, условие из ТЗ не выполнено, можно ставить баг!&lt;/p&gt;
  &lt;p id=&quot;UPnV&quot;&gt;А мы пока читаем дальше:&lt;/p&gt;
  &lt;blockquote id=&quot;3vvs&quot;&gt;Имя и емейл должны быть уникальными&lt;/blockquote&gt;
  &lt;p id=&quot;nSLH&quot;&gt;Раз должны, то будет ошибка в случае неуникальности. А мы решили вынести тестирование негативных сценариев отдельно. Видите, решение тестировать альтернативы отдельно от негативного сразу оказалось не самым удобным — куда лучше просто читать ТЗ и каждый пункт проверять. Так хоть не запутаешься, что проверил, а что ещё нет… Однако в рамках статьи мы всё-таки рассмотрим негативные тесты отдельно.&lt;/p&gt;
  &lt;p id=&quot;Gd6A&quot;&gt;Пока же смотрим дальше — а всё, кончилось ТЗ, метод то простенький. Тогда переходим к негативу!&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;cfX3&quot;&gt;4. Негативные сценарии&lt;/h3&gt;
  &lt;p id=&quot;PivE&quot;&gt;По факту это проверка сообщений об ошибках. Смотрим на метод и думаем, как его можно сломать? Сначала бизнесово, а потом API-шно…&lt;/p&gt;
  &lt;p id=&quot;VYZE&quot;&gt;С бизнесовой точки зрения очень удобно, когда все ошибки прописывают прямо в ТЗ. Получается руководство к действию! Это можно быть разделение на «Особенности использования» и «Исключительные ситуации», как в &lt;a href=&quot;https://testbase.atlassian.net/wiki/spaces/FOLKS/pages/845283331/Folks.search&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;Folks&lt;/u&gt;&lt;/a&gt; (логин для входа &lt;a href=&quot;http://okiseleva.blogspot.com/2017/07/jira-confluence.html&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;тут&lt;/u&gt;&lt;/a&gt;). Тогда тестируем блок «Исключительные ситуации».&lt;/p&gt;
  &lt;p id=&quot;cmaA&quot;&gt;Или вот описание &lt;a href=&quot;https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;Jira Cloud REST API&lt;/u&gt;&lt;/a&gt;, выберем в левом навигационном меню какой-нибудь метод, например «Delete avatar». Там есть описание метода, а потом в блоке Responces переключалки между кодами ответов.&lt;/p&gt;
  &lt;p id=&quot;4hgg&quot;&gt;Ну так вот все желтые коды — это ошибки. Открываем каждую, читаем «Returned if» и выполняем это условие, очень удобно:&lt;/p&gt;
  &lt;figure id=&quot;GFCV&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f51/bc1/a06/f51bc1a0675f4b3a6fa9b43d7168c252.png&quot; width=&quot;921&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Vvw6&quot;&gt;В общем, если есть отдельно про ошибки — класс, проверяем по ТЗ. А потом ещё думаем сами, что там могло быть пропущено.&lt;/p&gt;
  &lt;p id=&quot;VZnO&quot;&gt;Плюс проверяем логику ошибок в API, но о ней чуть позже. Сначала бизнес-логика, потом уже серебряная пуля типа well formed json.&lt;/p&gt;
  &lt;p id=&quot;DUVw&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;W4BY&quot;&gt;Ограничение в ТЗ:&lt;/p&gt;
  &lt;blockquote id=&quot;nEW0&quot;&gt;Имя и емейл должны быть уникальными&lt;/blockquote&gt;
  &lt;p id=&quot;VG29&quot;&gt;Для проверки нам надо сделать неуникальным:&lt;/p&gt;
  &lt;ol id=&quot;8eU9&quot;&gt;
    &lt;li id=&quot;7UKh&quot;&gt;имя&lt;/li&gt;
    &lt;li id=&quot;Eeme&quot;&gt;емейл&lt;/li&gt;
    &lt;li id=&quot;zfvC&quot;&gt;оба поля сразу&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;OW4Q&quot;&gt;Можем взять за основу наш исходный запрос, который 1 раз создался:&lt;/p&gt;
  &lt;pre id=&quot;O4VD&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli754@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;bBHw&quot;&gt;И варьируем его&lt;/p&gt;
  &lt;p id=&quot;b7rF&quot;&gt;1. Уникальный емейл, дубликат имени&lt;/p&gt;
  &lt;pre id=&quot;0IIy&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli{{$randomInt}}@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;PKO5&quot;&gt;2. Уникальное имя, дубликат емейл&lt;/p&gt;
  &lt;pre id=&quot;ug1b&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli754@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;rOIr&quot;&gt;3. Дубликаты сразу имени и емейл&lt;/p&gt;
  &lt;pre id=&quot;6qXk&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli754@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;wSmD&quot;&gt;И смотрим на ответ. Понятно ли нам из сообщения об ошибке, что именно пошло не так? А статус-код соответствует типу ошибки?&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;DhSp&quot;&gt;5. Параметры запроса&lt;/h3&gt;
  &lt;p id=&quot;dgll&quot;&gt;На входе мы передаем какие-то параметры. И теперь нам нужно взять каждый параметр и проверить отдельно. Как проверяем:&lt;/p&gt;
  &lt;ol id=&quot;oMXG&quot;&gt;
    &lt;li id=&quot;YfBq&quot;&gt;Обязательность&lt;/li&gt;
    &lt;li id=&quot;Ftrh&quot;&gt;Перестановка мест слагаемых&lt;/li&gt;
    &lt;li id=&quot;jt7s&quot;&gt;Бизнес-логика&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;Yfxp&quot;&gt;Про первые 2 пункта мы поговорим чуть позже, сейчас сосредоточимся на бизнес-логике.&lt;/p&gt;
  &lt;p id=&quot;vNXX&quot;&gt;Вот у вас есть параметры запроса. Как их проверять? Если вы впали в ступор сейчас, то просто представьте себе, что это не API, а GUI. Что у вас в интерфейсе есть форма ввода с этими полями? Как будете тестировать? Вот ровно так и тестируйте, выкинув разве что попытку убрать ограничение на клиенте (снять с поля &lt;em&gt;maxlenght&lt;/em&gt;).&lt;/p&gt;
  &lt;p id=&quot;T7Ve&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Ml1G&quot;&gt;По ТЗ входные параметры:&lt;/p&gt;
  &lt;p id=&quot;jzBN&quot;&gt;&lt;strong&gt;Имя параметра&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;M5QO&quot;&gt;&lt;strong&gt;Тип&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;iEIa&quot;&gt;&lt;strong&gt;Обязательный?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;w9Uj&quot;&gt;&lt;strong&gt;Описание&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Dzzc&quot;&gt;email&lt;/p&gt;
  &lt;p id=&quot;G46C&quot;&gt;строка&lt;/p&gt;
  &lt;p id=&quot;kxXZ&quot;&gt;да&lt;/p&gt;
  &lt;p id=&quot;x2ZQ&quot;&gt;email пользователя&lt;/p&gt;
  &lt;p id=&quot;131e&quot;&gt;name&lt;/p&gt;
  &lt;p id=&quot;iXyX&quot;&gt;строка&lt;/p&gt;
  &lt;p id=&quot;EaE0&quot;&gt;да&lt;/p&gt;
  &lt;p id=&quot;QXAK&quot;&gt;имя пользователя&lt;/p&gt;
  &lt;p id=&quot;kbyV&quot;&gt;password&lt;/p&gt;
  &lt;p id=&quot;scbr&quot;&gt;строка&lt;/p&gt;
  &lt;p id=&quot;PUuA&quot;&gt;да&lt;/p&gt;
  &lt;p id=&quot;5MXp&quot;&gt;пароль&lt;/p&gt;
  &lt;p id=&quot;pBLh&quot;&gt;Тестируем каждый параметр в отдельности. И тут, как и в GUI, надо понимать:&lt;/p&gt;
  &lt;ul id=&quot;IwRr&quot;&gt;
    &lt;li id=&quot;ukiC&quot;&gt;Есть ли какие-то проверки у поля? Проверяется ли email по маске email-а? Имя выверяется по справочникам? Или это “просто строка, как прислали, так и сохранил?”&lt;/li&gt;
    &lt;li id=&quot;Cxie&quot;&gt;Куда данные идут дальше, где отображаются? В приветствии, в отчете, в личном кабинете, где?&lt;/li&gt;
    &lt;li id=&quot;9c5Q&quot;&gt;Как они потом используются? На емейл придет письмо?&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h4 id=&quot;sHOL&quot;&gt;email&lt;/h4&gt;
  &lt;p id=&quot;NXSg&quot;&gt;Вроде доп. проверок разработчик не делал, но точно я этого не знаю. Поле базовое, может есть прям во фреймворке какие-то проверки, или в интернете скопипастил… Так что тут стоит убедиться, что email корректный.&lt;/p&gt;
  &lt;p id=&quot;jTzP&quot;&gt;Можно взять за основу &lt;a href=&quot;http://akkaparallel.blogspot.com/2013/06/email.html&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;вот этот чек-лист&lt;/u&gt;&lt;/a&gt;, но часть проверок скомбинировать&lt;/p&gt;
  &lt;ol id=&quot;CSm7&quot;&gt;
    &lt;li id=&quot;gun2&quot;&gt;Корректный существующий email, куда может прийти почта — подставляем свой (начинаем всегда с корректного)&lt;/li&gt;
    &lt;li id=&quot;w1lt&quot;&gt;Верхний регистр, цифры в имени пользователя и доменной части — &lt;a href=&quot;mailto:TEST77@mail9.ru&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;TEST77@mail9.ru&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;aTU5&quot;&gt;Email с дефисами и нижним подчеркиванием — test_user-1@mail_test-1.com&lt;/li&gt;
    &lt;li id=&quot;dDk6&quot;&gt;Email с точками в имени пользователя и парой точек в доменной части — &lt;a href=&quot;mailto:test.user@test.test.test.ru&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;test.user@test.test.test.ru&lt;/u&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;VA8J&quot;&gt;А дальше идут интересные тесты, которые по идее должны падать, но упадут ли в Users, есть ли там такие проверки?&lt;/p&gt;
  &lt;ol id=&quot;EqDk&quot;&gt;
    &lt;li id=&quot;2BbW&quot;&gt;Email без точек в доменной части — test@mailcom&lt;/li&gt;
    &lt;li id=&quot;lexN&quot;&gt;Превышение длины email (&amp;gt;320 символов)&lt;/li&gt;
    &lt;li id=&quot;qfSB&quot;&gt;Отсутствие @ в email — testmail.ru&lt;/li&gt;
    &lt;li id=&quot;KWGq&quot;&gt;Email с пробелами в имени пользователя — test user@mail.ru&lt;/li&gt;
    &lt;li id=&quot;evZG&quot;&gt;Email с пробелами в доменной части — test@ma il.ru&lt;/li&gt;
    &lt;li id=&quot;V4h0&quot;&gt;Email без имени пользователя — @mail.ru&lt;/li&gt;
    &lt;li id=&quot;zOQv&quot;&gt;Email без доменной части — test@&lt;/li&gt;
    &lt;li id=&quot;TBeq&quot;&gt;Некорректный домен первого уровня (допустимо 2-6 букв после точки: .ru) — test@mail.urururururu&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;vSsM&quot;&gt;Помним, что имя должно быть быть уникальным при этом, потому что негативные тесты мы не смешиваем, только если в этом состоит сам тест “а что, если несколько полей сразу плохие”. Так что пример запроса:&lt;/p&gt;
  &lt;pre id=&quot;KiCd&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;test@mailcom&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;0wL0&quot;&gt;И сервер отвечает — некорректный емейл!&lt;/p&gt;
  &lt;figure id=&quot;e0fh&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ec4/f68/2f4/ec4f682f43da4284a1842fedd8189b90.png&quot; width=&quot;505&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;BC2V&quot;&gt;Так что проверки на емейл нужны, особенно — на некорректный.&lt;/p&gt;
  &lt;h4 id=&quot;wMl6&quot;&gt;name&lt;/h4&gt;
  &lt;p id=&quot;275M&quot;&gt;Имя можно тестировать по разному. Если по нему определяется пол, тесты будут одни, если предлагаются подсказки, другие, а если это простая строка — третьи.&lt;/p&gt;
  &lt;p id=&quot;q055&quot;&gt;Так вот, в Users имя — это простая строка. Пол по ней не определяется, оно просто сохраняется в системе, разве что в правом верхнем углу отображается&lt;/p&gt;
  &lt;figure id=&quot;ed9s&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/dc6/aa0/a08/dc6aa0a0807437e128c500a83ff39b50.png&quot; width=&quot;526&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;A4Gh&quot;&gt;Поэтому закапываться в “а теперь проверим мужское имя, и женское, и…” смысла нет.. Так что наша задача — проверить:&lt;/p&gt;
  &lt;ul id=&quot;lWS8&quot;&gt;
    &lt;li id=&quot;LvgA&quot;&gt;Что это правда простая строка и туда влезет всё, что можно&lt;/li&gt;
    &lt;li id=&quot;LEG9&quot;&gt;Максимальную длину изучить&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;egjq&quot;&gt;Ну и начинаем с позитивного теста. Итого получаем:&lt;/p&gt;
  &lt;ol id=&quot;Z0WL&quot;&gt;
    &lt;li id=&quot;tcRP&quot;&gt;Простое имя типа “Ольга”&lt;/li&gt;
    &lt;li id=&quot;TY1m&quot;&gt;Имя с разным регистром, разными буквами и спецсимволами (все спецсимволы можно перечислить) — если есть ограничение по длине, разобьем на разные тесты&lt;/li&gt;
    &lt;li id=&quot;G18o&quot;&gt;1 000 символов — ищем верхнюю границу, если она есть. Заодно смотрим, как это выглядит в интерфейсе и корректируем тест.&lt;/li&gt;
    &lt;li id=&quot;xpWI&quot;&gt;1 000 000 символов — ищем технологическую границу&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;Ueke&quot;&gt;Обратите внимание на то, что мы вроде как тестируем API-метод, но после его выполнения лезем в графический интерфейс и проверяем, как там выглядит результат нашего запроса.&lt;/p&gt;
  &lt;p id=&quot;CweS&quot;&gt;А всё почему? Потому что нет абстрактных методов, которые делают “ничего”, просто отправляются. Они все зачем-то нужны. В нашем случае — чтобы создать пользователя в системе. И важно понимать, а что будет потом с нашими данными? Будут ли они нормально отображаться в интерфейсе? Ведь если нет, то надо ставить ограничение на API-метод.&lt;/p&gt;
  &lt;p id=&quot;7A6t&quot;&gt;Поэтому помните, что API и GUI идут рука об руку, а не живут в разных мирах.&lt;/p&gt;
  &lt;h4 id=&quot;6P4L&quot;&gt;Password&lt;/h4&gt;
  &lt;p id=&quot;Ne26&quot;&gt;На пароле тоже никаких ограничений нет — мы это знаем, потому что уже отправляли запрос с паролем “1”. Вот если бы были всякие “нужны заглавные буквы” и прочее, мы бы провели тесты “а если пароль ненадежный” и посмотрели на качество сообщения об ошибке, а так тесты будут как у имени:&lt;/p&gt;
  &lt;ol id=&quot;dC1E&quot;&gt;
    &lt;li id=&quot;TPUP&quot;&gt;Обычный пароль типа 1&lt;/li&gt;
    &lt;li id=&quot;Znd0&quot;&gt;Смесь из разных регистров, разных букв и спецсимволов — если есть ограничение по длине или составу, разобьем на разные тесты&lt;/li&gt;
    &lt;li id=&quot;FMYm&quot;&gt;1 000 символов — ищем верхнюю границу, если она есть. Заодно смотрим, как это выглядит в интерфейсе и корректируем тест.&lt;/li&gt;
    &lt;li id=&quot;NYFc&quot;&gt;1 000 000 символов — ищем технологическую границу&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;VVW1&quot;&gt;6. Остальные тесты&lt;/h3&gt;
  &lt;p id=&quot;P34Z&quot;&gt;А дальше мы уже идем по специфике API:&lt;/p&gt;
  &lt;ul id=&quot;dmBO&quot;&gt;
    &lt;li id=&quot;VYqQ&quot;&gt;Перестановка мест слагаемых (заголовки, тело)&lt;/li&gt;
    &lt;li id=&quot;js1N&quot;&gt;Регистрозависимость (заголовки, тело)&lt;/li&gt;
    &lt;li id=&quot;jaO4&quot;&gt;Well formed xml / json&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;3tpa&quot;&gt;На конкретных примерах мы остановимся подробнее в следующих разделах. Просто важно не забывать про эти тесты. Этим и отличается API от GUI — тут нельзя снять границу из серии “убрать maxlenght”, зато можно и нужно проверить особенности API запросов.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;5ghE&quot;&gt;Что тестируем в запросе&lt;/h2&gt;
  &lt;h3 id=&quot;TKMW&quot;&gt;Заголовки (Headers)&lt;/h3&gt;
  &lt;p id=&quot;v5VG&quot;&gt;Заголовки должны где-то обрабатываться:&lt;/p&gt;
  &lt;p id=&quot;x0us&quot;&gt;— на сервере;&lt;/p&gt;
  &lt;p id=&quot;Aiub&quot;&gt;— на клиенте;&lt;/p&gt;
  &lt;p id=&quot;B2rO&quot;&gt;Иначе они не нужны, только лишний трафик гонять. Мы ведь передаем сообщение по сети, если интернет плохой, то каждый байт на счету. Зачем отправлять информацию, которую никто не использует?&lt;/p&gt;
  &lt;p id=&quot;mjVR&quot;&gt;Так что разработчики используют «&lt;strong&gt;Принцип меньшего зла»:&lt;/strong&gt; заголовок или кем-то обрабатывается, или он вообще не нужен.&lt;/p&gt;
  &lt;p id=&quot;bUfK&quot;&gt;Если заголовка нет:&lt;/p&gt;
  &lt;p id=&quot;erVv&quot;&gt;— используется дефолтный, прописанный в коде;&lt;/p&gt;
  &lt;p id=&quot;Pktt&quot;&gt;— он вообще не нужен;&lt;/p&gt;
  &lt;blockquote id=&quot;DCXn&quot;&gt;Язык должен указываться всегда, иначе непонятно, как вернуть ответ от сервера. Но разработчик может в код зашить русский язык, и тогда даже если вы передадите заголовок «Accept-Language: en-US», то ответ получите на русском.Почему? Потому что разработчик игнорирует этот заголовок, он его не считывает из запроса в принципе. Его право =)&lt;/blockquote&gt;
  &lt;p id=&quot;SFbt&quot;&gt;&lt;strong&gt;Возможные ситуации, которые надо проверить&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;PcBC&quot;&gt;Заголовок не передан, как система реагирует:&lt;/p&gt;
  &lt;p id=&quot;s0UZ&quot;&gt;— выдает ошибку → понятно ли, что мне надо сделать?&lt;/p&gt;
  &lt;p id=&quot;DawU&quot;&gt;— применяет поведение по умолчанию (если язык не передан, используй русский)&lt;/p&gt;
  &lt;p id=&quot;hcgh&quot;&gt;Заголовок передан:&lt;/p&gt;
  &lt;p id=&quot;L2cC&quot;&gt;— верно&lt;/p&gt;
  &lt;p id=&quot;UYVE&quot;&gt;— неверно → какая ошибка?&lt;/p&gt;
  &lt;p id=&quot;MtV3&quot;&gt;Плюс регистрозависимость. Согласно спецификации, все заголовки должны быть регистронезависимы. И неважно, как я их передаю. Могу в CamelCase (первая буква большая, остальные мелкие), могу в верхнем регистре, причем как значение заголовка, так и его название, могу как-то ещё:&lt;/p&gt;
  &lt;ul id=&quot;Xo5C&quot;&gt;
    &lt;li id=&quot;PGKz&quot;&gt;Accept: application/json&lt;/li&gt;
    &lt;li id=&quot;XH7K&quot;&gt;Accept: APPLICATION/JSON&lt;/li&gt;
    &lt;li id=&quot;iFL2&quot;&gt;ACCEPT: application/json&lt;/li&gt;
    &lt;li id=&quot;hOy8&quot;&gt;ACCEPT: APPLICATION/JSON&lt;/li&gt;
    &lt;li id=&quot;5fPT&quot;&gt;ACcePT: APPlicATIon/JSon&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;HBMo&quot;&gt;Проверить эти варианты — очень важно. Потому что за регистронезависимость отвечает разработчик, сама по себе из воздуха она не появится. Он должен прописать это в коде.&lt;/p&gt;
  &lt;p id=&quot;MzTm&quot;&gt;Был случай у моих коллег — заголовок проверили, всё работает. Но проверили по доке, прислали значения «как указано». Вот Accept может быть (как передаются входные данные):&lt;/p&gt;
  &lt;ul id=&quot;74vI&quot;&gt;
    &lt;li id=&quot;d2z8&quot;&gt;application/json&lt;/li&gt;
    &lt;li id=&quot;tkHC&quot;&gt;application/xml&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;wUxf&quot;&gt;А потом пользователи приходят и жалуются на ошибки «у вас плохой заголовок». При том, что заголовок они отправили правильный. Начали разбираться — запрос идет не напрямую на сервер, он проходит через прокси Nginx. А Nginx меняет заголовки на upper case: ACCEPT: APPLICATION/JSON.&lt;/p&gt;
  &lt;p id=&quot;M2u9&quot;&gt;Система к такому не готова, она ищет «Accept», не находит его и выдает ошибку. А переданный заголовок игнорирует. Так что проверять регистр — надо!&lt;/p&gt;
  &lt;p id=&quot;kIUl&quot;&gt;&lt;strong&gt;Итого — тестирование заголовков в API&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;bJuX&quot;&gt;
    &lt;li id=&quot;6peF&quot;&gt;Заголовки из документации работают (в целом)&lt;/li&gt;
    &lt;li id=&quot;6FEz&quot;&gt;А если какой-то не передать? (обязательность)&lt;/li&gt;
    &lt;li id=&quot;8GA1&quot;&gt;А если передать, но неправильно? (текст ошибки)&lt;/li&gt;
    &lt;li id=&quot;W5r2&quot;&gt;Позитивные тесты по доке&lt;/li&gt;
    &lt;li id=&quot;Zvy7&quot;&gt;Регистронезависимость заголовков&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;O1ak&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;ubhI&quot;&gt;В документации вообще ничего не сказано про заголовки. Поэтому проверяем, можно ли отправить сообщение без них. Идем на вкладку Headers и снимаем все галки, если они по каким-то причинам там стояли. Запрос сработал успешно:&lt;/p&gt;
  &lt;figure id=&quot;XDGZ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/030/091/51e/03009151ec44171e59f8b437c716ab27.png&quot; width=&quot;688&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;nifq&quot;&gt;Но обратите внимание, что в постмане есть ещё скрытые заголовки (hidden):&lt;/p&gt;
  &lt;figure id=&quot;3PUk&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/02d/0f8/199/02d0f819953517293d04c2f1406466e3.png&quot; width=&quot;342&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Oo2Y&quot;&gt;Это те заголовки, что генерирует сам постман. По сути постман — это клиент, помогающий нам отправить запрос на сервер. И у него есть какие-то свои фишечки, ограничения, заголовки опять же.&lt;/p&gt;
  &lt;p id=&quot;lWZs&quot;&gt;Можно нажать на это сообщение “(цифра) hidden” и раскрыть этот список (а потом всегда можно нажать на кнопку “hide hidden”:&lt;/p&gt;
  &lt;figure id=&quot;uhmv&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/bdc/a30/e45/bdca30e45442686bd3eb2a668f53de8a.png&quot; width=&quot;652&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3BiK&quot;&gt;Это некий стандарт, дефолтные значения по умолчанию. Тот же Cache-Control, раз вы его не передаете, по факту он вам не нужен, то есть как если бы вы указали “no-cache”.&lt;/p&gt;
  &lt;p id=&quot;SXdL&quot;&gt;Но учтите, что если снять тут все-все-все галки, система может выдать ошибку:&lt;/p&gt;
  &lt;figure id=&quot;kV93&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/0db/02a/ea8/0db02aea832880c2724607235104ee64.png&quot; width=&quot;694&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;cBbw&quot;&gt;Плохо ли это? Стоит ли заводить баг “в документации сказано, что можно без заголовков, а так не работает” — нет. Для начала попробуйте отправить запрос через curl и посмотрите на результат.&lt;/p&gt;
  &lt;p id=&quot;NzG1&quot;&gt;Помните, что Postman — это всё-таки клиент, у которого есть свои навороты. Так что пусть он их накручивает сколько влезет, эти хидден-заголовки тестировать особо не надо. А вот послать хотя бы разок честный curl — надо!&lt;/p&gt;
  &lt;p id=&quot;BY03&quot;&gt;Так что прячем hidden-заголовки и проверяем без них в этом пункте. Да, doregister без заголовков работает, всё ок.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;1BlI&quot;&gt;Тело запроса (body)&lt;/h3&gt;
  &lt;p id=&quot;0BjA&quot;&gt;Что мы тут тестируем:&lt;/p&gt;
  &lt;ol id=&quot;RAg2&quot;&gt;
    &lt;li id=&quot;Sqze&quot;&gt;Правильное тело (пример)&lt;/li&gt;
    &lt;li id=&quot;vnpl&quot;&gt;Различные параметры (обязательность, работа параметров)&lt;/li&gt;
    &lt;li id=&quot;IOM5&quot;&gt;Бизнес-логика&lt;/li&gt;
    &lt;li id=&quot;TXvf&quot;&gt;Ошибки: бизнес-логика&lt;/li&gt;
    &lt;li id=&quot;2LXp&quot;&gt;Перестановка мест слагаемых&lt;/li&gt;
    &lt;li id=&quot;mUAs&quot;&gt;Регистрозависимость&lt;/li&gt;
    &lt;li id=&quot;BFaO&quot;&gt;Ошибки: не well formed xml / json&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;IOC5&quot;&gt;Пункты 1-4 мы уже обсудили выше. Идем по ТЗ и каждую строчку изучаем и проверяем.&lt;/p&gt;
  &lt;p id=&quot;pHf3&quot;&gt;&lt;em&gt;Перестановка мест слагаемых&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;3PCj&quot;&gt;Это как раз особенность API, поэтому очень важно её проверить. Бизнес-логика и проверки “а что можно ввести в такое-то поле” одинаковы для GUI и API, а вот переставить поля местами в графическом интерфейсе не получится.&lt;/p&gt;
  &lt;p id=&quot;GRjC&quot;&gt;При этом в API это сделать проще простого. Мы ведь передаем пары “ключ-значение”. Что будет, если мы попробуем поменять их местами?&lt;/p&gt;
  &lt;p id=&quot;YfJT&quot;&gt;В идеале ничего не случится, потому что принимающая система должна из запрос цеплять информацию именно по названию ключа, а не делать “select *” и потом говорить “для первого поля из запрос проверь то, для второго сделай это…”.&lt;/p&gt;
  &lt;p id=&quot;2osd&quot;&gt;Ведь потом изменится входной запрос и у нас вся интеграция сломается! А это нехорошо… Так что смотрим как система реагирует на перестановки.&lt;/p&gt;
  &lt;p id=&quot;BGE7&quot;&gt;&lt;em&gt;Регистрозависимость&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;5mbE&quot;&gt;Вы же помните о том, что регистронезависимость не появляется из воздуха? Её делает разработчик. Поэтому и проверить “как ведет себя система” — тоже надо. И в заголовках, и в теле, и в параметрах URL — вообще везде, где есть символы.&lt;/p&gt;
  &lt;p id=&quot;PlT6&quot;&gt;&lt;em&gt;Ошибки в ответе от сервера&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;CpZb&quot;&gt;Всегда обязательно изучаем ошибки. Помимо ошибок в бизнес-логике есть ещё неправильно составленный запрос. То есть не well formed. Пробуем такой послать и смотрим на адекватность ошибки&lt;/p&gt;
  &lt;blockquote id=&quot;AxKy&quot;&gt;&lt;strong&gt;См также:&lt;/strong&gt;&lt;u&gt;&lt;a href=&quot;https://okiseleva.blogspot.com/2021/04/well-formed-xml.html&quot; target=&quot;_blank&quot;&gt;Правила Well Formed XML&lt;/a&gt;&lt;a href=&quot;https://okiseleva.blogspot.com/2021/05/well-formed-json.html&quot; target=&quot;_blank&quot;&gt;Правила Well Formed JSON&lt;/a&gt;&lt;/u&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;uZZM&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;ExDt&quot;&gt;По бизнес-логике мы уже прошли, теперь пойдем по API-части:&lt;/p&gt;
  &lt;p id=&quot;zs60&quot;&gt;&lt;em&gt;1. Перестановка мест слагаемых&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;IpED&quot;&gt;В json пробуем перестановку:&lt;/p&gt;
  &lt;pre id=&quot;RMyL&quot;&gt;{

    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,

    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,    

    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;

}&lt;/pre&gt;
  &lt;p id=&quot;85Sp&quot;&gt;Ура, работает! А как насчет form-data? Тоже всё ок, это хорошо:&lt;/p&gt;
  &lt;figure id=&quot;FoBn&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/dc0/806/c13/dc0806c1387d3ec871a191f2741fda10.png&quot; width=&quot;1066&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;BEIf&quot;&gt;&lt;em&gt;2. Регистрозависимость&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;GXon&quot;&gt;Мы уже поняли, что в Users регистронезависимости может и не быть. Поэтому проверим на одном поле для начала. И не email, а то с ним может быть ложная уверенность в корректной ошибке:&lt;/p&gt;
  &lt;pre id=&quot;lQoe&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,      &amp;quot;NAME&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,       &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;rnr6&quot;&gt;Запрос не сработал, увы: &lt;em&gt;&amp;quot;Параметр name является обязательным!&amp;quot;&lt;/em&gt;&lt;/p&gt;
  &lt;figure id=&quot;szGm&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/667/391/d2f/667391d2fe8bff5af0b983b9d22a3010.png&quot; width=&quot;1022&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;2KP8&quot;&gt;Названия ключей регистрозависимы. Это не очень хорошо, хотя и некритично. Такой баг разработчик может не захотеть исправлять, “пусть присылают по документации”. Ну что же, тогда единственным аргументом будет потом количество обращений в поддержку.&lt;/p&gt;
  &lt;p id=&quot;A0mM&quot;&gt;Но мы, по крайней мере, получили информацию по работе системы.&lt;/p&gt;
  &lt;p id=&quot;FaME&quot;&gt;&lt;em&gt;3. Well formed&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;1H9x&quot;&gt;У нас на входе json, смотрим его правила:&lt;/p&gt;
  &lt;ol id=&quot;yVNq&quot;&gt;
    &lt;li id=&quot;laAu&quot;&gt;Данные написаны в виде пар «ключ:значение»&lt;/li&gt;
    &lt;li id=&quot;XdVz&quot;&gt;Данные разделены запятыми&lt;/li&gt;
    &lt;li id=&quot;cATR&quot;&gt;Объект находится внутри фигурных скобок {}&lt;/li&gt;
    &lt;li id=&quot;TcpR&quot;&gt;Массив — внутри квадратных []&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;3EHz&quot;&gt;И пытаемся сломать. Вообще самая частая ошибка — это запятая после последней пары «ключ:значение». Мы обычно скопипастим строку из середины (вместе с запятой), поставим в конец объекта, а запятую удалить забудем. Получится как-то так:&lt;/p&gt;
  &lt;pre id=&quot;e7BY&quot;&gt;{

    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mailcom&amp;quot;,

    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,

    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;,

}&lt;/pre&gt;
  &lt;p id=&quot;17o0&quot;&gt;Отправляем такой запрос. М-м-м-м, ответ как-то не очень:&lt;/p&gt;
  &lt;figure id=&quot;Xfin&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f95/d42/1ac/f95d421ac508087570ab2aecf40491be.png&quot; width=&quot;965&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;S0xB&quot;&gt;Это постман мне настойчиво подсвечивает красным лишнюю запятую, а если вызов идет из кода и там подсветки нет, то как понять, что пошло не так? Из текста сообщения об ошибке. Только вот из такого текста разработчик очень долго будет угадывать, что не понравилось системе… Нехорошо, стоит завести баг.&lt;/p&gt;
  &lt;p id=&quot;eUP0&quot;&gt;Попробуем другие способы сломать формат:&lt;/p&gt;
  &lt;p id=&quot;kpO1&quot;&gt;— не в виде пар “ключ:значение”&lt;/p&gt;
  &lt;pre id=&quot;jZuo&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;jAYW&quot;&gt;Ответ будет такой же — &lt;em&gt;&amp;quot;Параметр email является обязательным!&amp;quot;&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;r9so&quot;&gt;Заметьте, что если мы “сломаем” так email, будет ложное ощущение, что система работает хорошо и правильно дает подсказку. А на самом деле нет…&lt;/p&gt;
  &lt;p id=&quot;LFM8&quot;&gt;Так что если уже замечали странности раньше, проверяем на другом поле — на пароле, а не емейле. И видим, что ошибка непонятная.&lt;/p&gt;
  &lt;p id=&quot;o2As&quot;&gt;— данные не разделены запятыми&lt;/p&gt;
  &lt;pre id=&quot;VYfL&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;TvkH&quot;&gt;— объект в квадратных скобках, а не фигурных&lt;/p&gt;
  &lt;pre id=&quot;s1eQ&quot;&gt;[    &amp;quot;email&amp;quot;: &amp;quot;test{{$randomInt}}@mail.com&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;]&lt;/pre&gt;
  &lt;p id=&quot;89a4&quot;&gt;Ответ везде одинаковый — &lt;em&gt;&amp;quot;Параметр email является обязательным!&amp;quot;&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;XVKR&quot;&gt;Не очень хорошо, в ожидаемый результат чек-листа проверок мы запишем что-то более «правильное» =)) Например, ошибка 400 и сообщение &lt;em&gt;&amp;quot;Не well formed json в запросе&amp;quot;&lt;/em&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;hN1f&quot;&gt;URL&lt;/h3&gt;
  &lt;p id=&quot;edKb&quot;&gt;Там тоже могут быть параметры. Обычно это в методе GET делается, прямо в параметры URL зашивается какая-то информация. Например, идентификатор элемента, который мы хотим получить.&lt;/p&gt;
  &lt;p id=&quot;SSh6&quot;&gt;Тестируем точно также, как если бы параметр был в теле:&lt;/p&gt;
  &lt;ol id=&quot;Efm9&quot;&gt;
    &lt;li id=&quot;jSIm&quot;&gt;Правильный параметр (из примера)&lt;/li&gt;
    &lt;li id=&quot;6QS8&quot;&gt;Обязательность (что, если параметр не указать?)&lt;/li&gt;
    &lt;li id=&quot;9pP7&quot;&gt;Бизнес-логика (тест-дизайн)&lt;/li&gt;
    &lt;li id=&quot;n8dI&quot;&gt;Регистрозависимость (если параметр текстовый)&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;fgMO&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере JIRA&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;BSGZ&quot;&gt;Почему не на примере Users? А потому что в методе doRegister нет параметров, которые передаются в URL. Да и вообще в Users их нету, там даже get через POST сделан, но сейчас не об этом…&lt;/p&gt;
  &lt;p id=&quot;Odbt&quot;&gt;Поищем примеры в &lt;a href=&quot;https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;Jira Cloud REST API&lt;/u&gt;&lt;/a&gt;. Например, метод «Get Issue», вот какой у него URL:&lt;/p&gt;
  &lt;pre id=&quot;cMvk&quot;&gt;GET /rest/api/3/issue/{issueIdOrKey}&lt;/pre&gt;
  &lt;p id=&quot;OgGI&quot;&gt;Мы передаем в URL или id задачи, или её ключ. Условно говоря, это или что-то типа “13005” или “TEST-1”.&lt;/p&gt;
  &lt;p id=&quot;0T69&quot;&gt;И вот тут мы уже можем развернуться!&lt;/p&gt;
  &lt;p id=&quot;w56K&quot;&gt;&lt;em&gt;Правильное значение&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;Ummh&quot;&gt;Базовый позитивный тест, что метод в целом работает. Вызываем обязательно и так, и так:&lt;/p&gt;
  &lt;ul id=&quot;sswx&quot;&gt;
    &lt;li id=&quot;VW8m&quot;&gt;13005&lt;/li&gt;
    &lt;li id=&quot;VId2&quot;&gt;TEST-1&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;EDpn&quot;&gt;&lt;em&gt;Обязательность&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;R1mg&quot;&gt;Попробуем не передать параметр:&lt;/p&gt;
  &lt;pre id=&quot;s8VC&quot;&gt;/rest/api/3/issue//rest/api/3/issue&lt;/pre&gt;
  &lt;p id=&quot;pwJ7&quot;&gt;&lt;em&gt;Тест-дизайн&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;nIQK&quot;&gt;Тут стоит подумать в тему состояний объекта. Пробуем получить:&lt;/p&gt;
  &lt;ul id=&quot;SslF&quot;&gt;
    &lt;li id=&quot;riHL&quot;&gt;Свежесозданную задачу&lt;/li&gt;
    &lt;li id=&quot;ghBj&quot;&gt;Несколько раз измененную / отредактированную&lt;/li&gt;
    &lt;li id=&quot;2P5J&quot;&gt;Заполненную по минимуму / по максимуму&lt;/li&gt;
    &lt;li id=&quot;BY2R&quot;&gt;В разных статусах&lt;/li&gt;
    &lt;li id=&quot;LsrJ&quot;&gt;Закрытую&lt;/li&gt;
    &lt;li id=&quot;8Jrk&quot;&gt;Удаленную&lt;/li&gt;
    &lt;li id=&quot;gXVl&quot;&gt;Не существующую (такого номера ещё нет — это отличается от “он есть в базе, но задача была закрыта”)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;30RN&quot;&gt;&lt;em&gt;Регистрозависимость&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;fVRz&quot;&gt;При передаче issueId этот пункт не проверить, цифры сами по себе регистронезависимы. Но если мы передаем задачу через &lt;em&gt;Key&lt;/em&gt;, то это уже символы. Значит, проверка актуальна:&lt;/p&gt;
  &lt;pre id=&quot;sOiQ&quot;&gt;/rest/api/3/issue/test-1/rest/api/3/issue/TEst-1&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;hzNS&quot;&gt;Тип метода&lt;/h3&gt;
  &lt;p id=&quot;LJEO&quot;&gt;Что будет, если мы “подменим” тип запроса?&lt;/p&gt;
  &lt;blockquote id=&quot;1Oux&quot;&gt;POST → GET (совсем разные типы запросов)POST → PUT (похожие типы)&lt;/blockquote&gt;
  &lt;p id=&quot;fQQ4&quot;&gt;Как система отреагирует? Она может или отработать “словно так и надо”, или выдать ошибку. И тут следим за тем, чтобы ошибка была внятной и понятной.&lt;/p&gt;
  &lt;p id=&quot;4Pf5&quot;&gt;А ещё может показаться, что игнорирование ошибок пользователя — это хорошо. Но далеко не всегда. Например, у меня был случай, когда на проекте обновили библиотеку и она стала намного жестче с ошибкам интеграции. Тут то и выяснилось, что запросы исходные системы присылали “кто во что горазд”.&lt;/p&gt;
  &lt;p id=&quot;QVj9&quot;&gt;Если бы система сразу падала, то на первичной интеграции пришлось бы поднапрячься побольше, зато дальнейшие переходы были бы бесшовными. А когда уже всё в продакшене, это будет стопить обновление релиза. Так что может, лучше заранее начать ловить за руку “ты мне какой-то треш” шлешь?&lt;/p&gt;
  &lt;p id=&quot;UgLf&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;TRLm&quot;&gt;Меняем в запросе тип метода с POST на GET — а ему всё равно, успешно!&lt;/p&gt;
  &lt;figure id=&quot;9kOW&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ebc/f08/8db/ebcf088db1defbda6b12353ddf521761.png&quot; width=&quot;689&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;tYPc&quot;&gt;Нельзя сказать, что это прям вау-поведение, но для Users это нормально =)&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;VhMS&quot;&gt;Что тестируем в ответе&lt;/h2&gt;
  &lt;h3 id=&quot;pUTi&quot;&gt;Тело ответа&lt;/h3&gt;
  &lt;p id=&quot;v2UG&quot;&gt;Чек-лист проверки:&lt;/p&gt;
  &lt;ol id=&quot;UBEf&quot;&gt;
    &lt;li id=&quot;1Tki&quot;&gt;Какие поля вернулись в ответе?&lt;/li&gt;
    &lt;li id=&quot;BHRj&quot;&gt;Значения в полях&lt;/li&gt;
    &lt;li id=&quot;intE&quot;&gt;Текст ошибок&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;AOss&quot;&gt;Поля в ответе нужно:&lt;/p&gt;
  &lt;ul id=&quot;dYkl&quot;&gt;
    &lt;li id=&quot;VCCt&quot;&gt;сравнить с ТЗ&lt;/li&gt;
    &lt;li id=&quot;Dka3&quot;&gt;сравнить между собой SOAP \ REST&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;GLLt&quot;&gt;Если у нас есть ТЗ — то всё понятно. Читаем, как должно быть, проверяем, как есть на самом деле. Смотрим на то, что все поля из требований вернулись, и что в них правильное значение. А то вдруг я сохраняю имя “Оля”, а там всегда сохраняется “Тестовый”... Очень удобно сразу автотесты писать в том же постмане, если отдельного фреймворка нет — идем по ТЗ и каждое поле выверяем.&lt;/p&gt;
  &lt;p id=&quot;xTd4&quot;&gt;Если ТЗ нет, то уже сложнее. Ищем «хранителя информации», расспрашиваем, проверяем, как работает на самом деле. Думаем, есть ли проблемы в текущем поведении. Нет? Ок, значит, так и надо.&lt;/p&gt;
  &lt;p id=&quot;Khxk&quot;&gt;Если в ответе сообщение об ошибке, то внимательно его изучаем. В API это ещё важнее, чем просто в графическом интерфейсе. Поймет ли пользователь, что именно он сделал не так, где именно ошибся? Помните, плохое сообщение об ошибке приведет к тому, что вас будут дергать по пустякам, вырывая из контекста.&lt;/p&gt;
  &lt;blockquote id=&quot;TD0x&quot;&gt;&lt;strong&gt;См также:&lt;/strong&gt;&lt;u&gt;&lt;a href=&quot;https://okiseleva.blogspot.com/2021/02/blog-post_27.html&quot; target=&quot;_blank&quot;&gt;Каким должно быть сообщение об ошибке&lt;/a&gt;&lt;a href=&quot;http://okiseleva.blogspot.com/2015/06/blog-post_8.html&quot; target=&quot;_blank&quot;&gt;Сообщения об ошибках — тоже документация, тестируйте их!&lt;/a&gt;&lt;/u&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;Nwzn&quot;&gt;Если у вас в системе два интерфейса — SOAP и REST, нужно проверить оба. Обычно они должны быть идентичны. Да и в коде это обеспечивается условно говоря двойной аннотацией “сделай и soap, и rest сгенери”, разработчик не дублирует всю функциональность дважды, а просто “включает” API.&lt;/p&gt;
  &lt;p id=&quot;xJ9r&quot;&gt;В таком случае действительно всё будет работать идентично, кроме пустых полей в ответе. Что будет, если какое-то поле не заполнено? Может легко быть такая ситуация:&lt;/p&gt;
  &lt;p id=&quot;pbZU&quot;&gt;— SOAP возвращает пустые поля;&lt;/p&gt;
  &lt;p id=&quot;dmoV&quot;&gt;— REST нет.&lt;/p&gt;
  &lt;p id=&quot;eTWr&quot;&gt;Более того, это даже может быть нормально! Например, исходно писался только SOAP-интерфейс, и было правило возвращать все поля, даже пустые. Потом решили стать модными, молодежными, подключили REST. И решили там поля пустые не возвращать.&lt;/p&gt;
  &lt;p id=&quot;e65T&quot;&gt;К тому же в SOAP всегда есть схема WSDL, где указаны обязательные поля. Значит, они будут возвращаться в ответе. В ресте же схема WADL необязательна, да и там любят придерживаться принципа минимальных чернил, лишнего не выводить.&lt;/p&gt;
  &lt;p id=&quot;3HHI&quot;&gt;В общем, проверьте обязательно, как методы срабатывают на:&lt;/p&gt;
  &lt;ul id=&quot;U4C1&quot;&gt;
    &lt;li id=&quot;jHJ6&quot;&gt;Отсутствие данных на входе (поле не пришло вообще / пришло пустое)&lt;/li&gt;
    &lt;li id=&quot;vzdT&quot;&gt;Пустые поля на выходе&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;137A&quot;&gt;Если по разному, то это должно быть описано в доке!&lt;/p&gt;
  &lt;p id=&quot;YEbu&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;FW8p&quot;&gt;Сначала отправляем базовый запрос и там, и там, как в документации. Но уже по документации мы можем заметить, что набор поле в ответах разный. В SOAP перечислены все поля юзера, включая кличку кошечки, собачки итд… В REST же несколько базовых полей, и всё.&lt;/p&gt;
  &lt;p id=&quot;afrQ&quot;&gt;Как так вышло? Очень просто. Для реста набор полей согласовали, разработчик сделал. Потом я сказала, что хочу ещё и SOAP. А там нужна схема WSDL, разработчик с ней особо не парился. Есть сущность “user”? Ну её и вернем в ответе. А в сущности как раз много полей…&lt;/p&gt;
  &lt;p id=&quot;ixeN&quot;&gt;Мне не критично, так что менять не стали, да и вообще отличный пример «да, и так бывает» же! =))&lt;/p&gt;
  &lt;p id=&quot;KWUK&quot;&gt;Ок, давайте теперь посмотрим на особенности API, ведь всю бизнес-логику перетестировать в SOAP смысла нет, она должна совпадать… Ну разве что вы совсем не верите своим разработчикам… Или кейсы очень важные. А так — бизнес-логику смотрим один раз, а потом переходим в особенностям API.&lt;/p&gt;
  &lt;p id=&quot;Imdb&quot;&gt;&lt;em&gt;Перестановка мест слагаемых&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;klCR&quot;&gt;Поменяем местами name и email — ой ёй ёй!&lt;/p&gt;
  &lt;figure id=&quot;BTB3&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/259/568/7bd/2595687bd269f83389bb7d4ab7aff6c8.png&quot; width=&quot;874&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;B9oj&quot;&gt;Система пишет &lt;em&gt;«Некоректный email Имечко 666»&lt;/em&gt;. Это значит, что она ориентируется не названия полей, передаваемые в тегах, а на их порядковых номер. И это ОЧЕНЬ ПЛОХО, на такое стоит идти ставить баг.&lt;/p&gt;
  &lt;p id=&quot;41eX&quot;&gt;Тем более обоснование у нас есть — неединообразно работает. REST вот от перестановки не зависит, и SOAP не должен.&lt;/p&gt;
  &lt;p id=&quot;rgJm&quot;&gt;А ещё слово «Некоректный» написано неправильно, там должно быть две буквы “р”. Проверяем в REST, посылая заведомо плохой емейл — да, и там ошибка. Надо бы исправить. Текстовку ошибок вычитываем внимательно!&lt;/p&gt;
  &lt;p id=&quot;wWN9&quot;&gt;&lt;em&gt;Регистрозависимость&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;SP6N&quot;&gt;Каждый тег регистрозависим сам по себе — открывающий и закрывающий должны совпадать по написанию, в том числе по регистру. Если это сломать, будет точно плохой запрос, но мы начнем с условно хорошего — оба тега в капс-локе:&lt;/p&gt;
  &lt;pre id=&quot;n8wv&quot;&gt;&amp;lt;EMAIL&amp;gt;ggg55555@mail.com&amp;lt;/EMAIL&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;LT3T&quot;&gt;Работает!&lt;/p&gt;
  &lt;figure id=&quot;jPEf&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/8b9/087/7f4/8b90877f4bc74b1c595f5e9d6c5bdb7d.png&quot; width=&quot;996&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;te1y&quot;&gt;А вот теперь попробуем разный регистр внутри тегов (в json такую проверку не сделать, это особенно XML, дублирование названия поля):&lt;/p&gt;
  &lt;pre id=&quot;Joz8&quot;&gt;&amp;lt;EMAIL&amp;gt;ggg55555@mail.com&amp;lt;/email&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;Fo03&quot;&gt;Не работает — Bad Request. Чтож, вполне логично.&lt;/p&gt;
  &lt;p id=&quot;0OF0&quot;&gt;&lt;em&gt;Well formed XML&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;mcCf&quot;&gt;Что, если сломать XML? Скажем, оставить закрывающий тег «/email» без второй угловой скобки:&lt;/p&gt;
  &lt;pre id=&quot;p9IS&quot;&gt;     &amp;lt;wrap:doRegister&amp;gt;         &amp;lt;email&amp;gt;ggg5555@mail.com&amp;lt;/email         &amp;lt;name&amp;gt;Имечко 666&amp;lt;/name&amp;gt;         &amp;lt;password&amp;gt;1&amp;lt;/password&amp;gt;      &amp;lt;/wrap:doRegister&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;906a&quot;&gt;Возвращается ошибка&lt;/p&gt;
  &lt;pre id=&quot;uUsZ&quot;&gt;&amp;lt;faultcode&amp;gt;SOAP-ENV:Client&amp;lt;/faultcode&amp;gt;&amp;lt;faultstring&amp;gt;Bad Request&amp;lt;/faultstring&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;mgih&quot;&gt;Не супер информативно, но в целом ясно, что мы где-то с запросом накосячили. И если такой текст именно на well formed, то и ладно. Тогда по нему будет сразу понятно, в чем именно проблема. Посмотрим дальше.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ocof&quot;&gt;Статус-коды&lt;/h3&gt;
  &lt;p id=&quot;FWzg&quot;&gt;Разработчик может использовать &lt;a href=&quot;https://developer.mozilla.org/ru/docs/Web/HTTP/Status&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;стандартные коды ответов&lt;/u&gt;&lt;/a&gt;,&lt;/p&gt;
  &lt;ul id=&quot;Hb4X&quot;&gt;
    &lt;li id=&quot;GbeO&quot;&gt;2хх — все хорошо&lt;/li&gt;
    &lt;li id=&quot;aQaC&quot;&gt;4хх — ошибка на клиенте (в запросе)&lt;/li&gt;
    &lt;li id=&quot;vnGr&quot;&gt;5хх — ошибка на сервере&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ymxZ&quot;&gt;А может придумать свои:&lt;/p&gt;
  &lt;ul id=&quot;iG52&quot;&gt;
    &lt;li id=&quot;ugkr&quot;&gt;570 — пустой ответ на поиск;&lt;/li&gt;
    &lt;li id=&quot;ppZS&quot;&gt;571 — нашли одного ФЛ;&lt;/li&gt;
    &lt;li id=&quot;tUuA&quot;&gt;572 — нашли несколько ИП;&lt;/li&gt;
    &lt;li id=&quot;96zM&quot;&gt;573 — нашли только ИП;&lt;/li&gt;
    &lt;li id=&quot;g2ua&quot;&gt;…&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;cCQ9&quot;&gt;Разработчик может даже перекрыть стандартные:&lt;/p&gt;
  &lt;p id=&quot;6bHE&quot;&gt;400 — Bad Request&lt;br /&gt;↓&lt;br /&gt;400 — Internal Server Error&lt;/p&gt;
  &lt;p id=&quot;vqlR&quot;&gt;Но так лучше не делать =))) Просто знайте, что возможность такая имеется.&lt;/p&gt;
  &lt;p id=&quot;jG9K&quot;&gt;Если разработчик ленивый и не настроил коды, то вы будете огребать на любую ошибку стандартный код: 400 Bad Request. Неверный заголовок? Ошибка 400. Неверное тело? Ошибка 400. Проблемы в бизнес-логике? Ошибка 400… Ну и как тут разобраться, что именно надо исправлять?&lt;/p&gt;
  &lt;p id=&quot;fa9U&quot;&gt;Или ещё “лучше”, разработчик может сказать “всегда возвращай код 200”. И это очень нехорошо, ведь именно по коду мы ориентируемся в первую очередь: всё хорошо или что-то плохо?&lt;/p&gt;
  &lt;p id=&quot;UrUw&quot;&gt;Поэтому статус-код проверяем всегда, обращаем на него внимание. Ну а если в методе собственные статусы (как, например, в методе &lt;a href=&quot;https://testbase.atlassian.net/wiki/spaces/USERS/pages/1249378773/MagicSearch&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;MagicSearch&lt;/u&gt;&lt;/a&gt;)&lt;/p&gt;
  &lt;p id=&quot;rz0d&quot;&gt;&lt;strong&gt;&lt;u&gt;Практика на примере Users&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;7btS&quot;&gt;На статус надо было обращать внимание всегда, чтобы не дублировать снова все тесты. Но сейчас просто дернем “хороший” и “плохой” запросы.&lt;/p&gt;
  &lt;p id=&quot;mxIk&quot;&gt;Хороший — статус 200, всё ок:&lt;/p&gt;
  &lt;figure id=&quot;XO6Y&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/e85/783/3b8/e857833b8348d97264b63ddffcf5efdf.png&quot; width=&quot;694&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iW81&quot;&gt;Плохой — ой, статус снова 200, хотя мы видим сообщение об ошибке:&lt;/p&gt;
  &lt;figure id=&quot;2Acp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/c73/adf/eb8/c73adfeb87d93b8dc2bd9eeb6ef09613.png&quot; width=&quot;689&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;XWdj&quot;&gt;Нехорошо! На это надо ставить баг.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;hUQM&quot;&gt;Итоговый чек-лист проверки doRegister&lt;/h2&gt;
  &lt;p id=&quot;rs8h&quot;&gt;Помним, что в первую очередь проверяем бизнес-логику. А потом уже всякие API-штучки, куда входят:&lt;/p&gt;
  &lt;ul id=&quot;1zsd&quot;&gt;
    &lt;li id=&quot;9Cvw&quot;&gt;Регистрозависимость&lt;/li&gt;
    &lt;li id=&quot;ctaP&quot;&gt;Перестановка мест параметров&lt;/li&gt;
    &lt;li id=&quot;9jZy&quot;&gt;Well formed запрос&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h4 id=&quot;ppfK&quot;&gt;Базовый тест&lt;/h4&gt;
  &lt;p id=&quot;2sUg&quot;&gt;&lt;em&gt;Базовый тест тщательно выверяет каждое поле из “корректного” ответа. Проверяет, как вызов API-метода влияет на отображение в GUI… Поэтому его пропишем текстом, а остальные тесты соберем в табличку.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;fG6A&quot;&gt;1. Проверка примера из ТЗ (но имя и емейл меняем на уникальные)&lt;/p&gt;
  &lt;pre id=&quot;Rgdo&quot;&gt;{    &amp;quot;email&amp;quot;: &amp;quot;milli{{$randomInt}}@mail.ru&amp;quot;,    &amp;quot;name&amp;quot;: &amp;quot; Машенька{{$randomInt}}&amp;quot;,    &amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;8AFb&quot;&gt;&lt;strong&gt;ОР: &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;pkLf&quot;&gt;1. Статус 200&lt;/p&gt;
  &lt;p id=&quot;Rtqn&quot;&gt;2. В ответе следующий набор полей:&lt;/p&gt;
  &lt;pre id=&quot;QCr2&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;, (то имя, что мы отправили)&amp;quot;avatar&amp;quot;: &amp;quot;http://users.bugred.ru//tmp/default_avatar.jpg&amp;quot;, (в этом методе всегда такой урл стандартной аватарки)&amp;quot;password&amp;quot;: &amp;quot;4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a&amp;quot;,&amp;quot;birthday&amp;quot;: 0,&amp;quot;email&amp;quot;: &amp;quot;milli754@mail.com&amp;quot;, (тот емейл, мы мы отправили)&amp;quot;gender&amp;quot;: &amp;quot;&amp;quot;,&amp;quot;date_start&amp;quot;: 0,&amp;quot;hobby&amp;quot;: &amp;quot;&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;ekVt&quot;&gt;3. Пользователь добавлен в общий список. Проверяем через GUI — &lt;a href=&quot;http://users.bugred.ru/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;http://users.bugred.ru/&lt;/u&gt;&lt;/a&gt;. Ищем поиском — есть!&lt;/p&gt;
  &lt;figure id=&quot;w5Ef&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4ca/0f8/10e/4ca0f810e2d696d30d4aaa481cc8c3b8.png&quot; width=&quot;1501&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;rAIg&quot;&gt;Проверяем все поля:&lt;/p&gt;
  &lt;ul id=&quot;k2dD&quot;&gt;
    &lt;li id=&quot;MNUC&quot;&gt;Емейл правильный, какой мы отправляли.&lt;/li&gt;
    &lt;li id=&quot;grZ4&quot;&gt;Автор «rest», что логично.&lt;/li&gt;
    &lt;li id=&quot;rlLI&quot;&gt;Дата изменения — сегодня, что тоже правильно.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;WPnC&quot;&gt;4. Под пользователем можно войти в систему — нажимаем “Войти”, вводим емейл из запроса, пароль из запроса, проверяем авторизацию.&lt;/p&gt;
  &lt;h4 id=&quot;0fOU&quot;&gt;Остальные тесты&lt;/h4&gt;
  &lt;p id=&quot;5zee&quot;&gt;&lt;strong&gt;Бизнес-логика из ТЗ&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;fp4c&quot;&gt;Уникальный емейл, дубликат имени&lt;/p&gt;
  &lt;p id=&quot;Q6nq&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;sZnw&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;milli&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.ru&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;kQoi&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;jHwk&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;8BdR&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;TUR3&quot;&gt;&lt;strong&gt;ОР: &lt;/strong&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;kU2W&quot;&gt;В теле ошибка: &amp;quot;name (переданное имя) уже есть в базе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;z7lB&quot;&gt;Уникальное имя, дубликат емейл&lt;/p&gt;
  &lt;p id=&quot;8luU&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;nxgY&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;milli754@mail.ru&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;p6UC&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;79VZ&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;JYO2&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;5biR&quot;&gt;&lt;strong&gt;ОР: &lt;/strong&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;jwei&quot;&gt;В теле ошибка: &amp;quot;email (переданный email) уже есть в базе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;zXBW&quot;&gt;Дубликаты сразу имени и емейл&lt;/p&gt;
  &lt;p id=&quot;6HY8&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;R0q6&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;milli754@mail.ru&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;lcg8&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька562&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;tvUY&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;mbov&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;Q22A&quot;&gt;&lt;strong&gt;ОР: &lt;/strong&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;kthS&quot;&gt;В теле ошибка: &amp;quot;email (переданный email) уже есть в базе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;adra&quot;&gt;&lt;strong&gt;Параметр email&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;GAvu&quot;&gt;Корректный существующий email, куда может прийти почта — подставляем свой (начинаем всегда с корректного)&lt;/p&gt;
  &lt;p id=&quot;Ajsy&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;KlF1&quot;&gt;Верхний регистр, цифры в имени пользователя и доменной части — &lt;a href=&quot;mailto:TEST77@mail9.ru&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;TEST77@mail9.ru&lt;/u&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;LpDS&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;HcPS&quot;&gt;Email с дефисами и нижним подчеркиванием — test_user-1@mail_test-1.com&lt;/p&gt;
  &lt;p id=&quot;dwKC&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;gADd&quot;&gt;Email с точками в имени пользователя и парой точек в доменной части — test.user@test.test.test.ru&lt;/p&gt;
  &lt;p id=&quot;dg8c&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;Urb5&quot;&gt;Email без точек в доменной части — test@mailcom&lt;/p&gt;
  &lt;p id=&quot;ZBXY&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;3KFC&quot;&gt;Превышение длины email (&amp;gt;320 символов)&lt;/p&gt;
  &lt;p id=&quot;sn0Q&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;dbe4&quot;&gt;Отсутствие @ в email — testmail.ru&lt;/p&gt;
  &lt;p id=&quot;SaJj&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;J3AU&quot;&gt;Email с пробелами в имени пользователя — test user@mail.ru&lt;/p&gt;
  &lt;p id=&quot;nV1J&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;IPpB&quot;&gt;Email с пробелами в доменной части — test@ma il.ru&lt;/p&gt;
  &lt;p id=&quot;9veT&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;AEHn&quot;&gt;Email без имени пользователя — @mail.ru&lt;/p&gt;
  &lt;p id=&quot;0EDU&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;yOKE&quot;&gt;Email без доменной части — test@&lt;/p&gt;
  &lt;p id=&quot;gOmg&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;Qn9g&quot;&gt;Некорректный домен первого уровня (допустимо 2-6 букв после точки: .ru) — test@mail.urururururu&lt;/p&gt;
  &lt;p id=&quot;cBVU&quot;&gt;Статус 400, ошибка «email некорректный»&lt;/p&gt;
  &lt;p id=&quot;H4GE&quot;&gt;&lt;strong&gt;Параметр name&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;fByu&quot;&gt;Простое имя типа “Ольга”&lt;/p&gt;
  &lt;p id=&quot;Kapd&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;i98K&quot;&gt;Разный регистр, буквы и спецсимволы:&lt;/p&gt;
  &lt;p id=&quot;pyzY&quot;&gt;Mixa1234567890&amp;#x60;-=[]\;’/.,~!@#$%^&amp;amp;*()_+}{:”?&amp;gt;&amp;lt;|Ё_+ХЪ/ЖЭБЮ,ёхъ\-=.&lt;/p&gt;
  &lt;p id=&quot;bB4H&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;qmTq&quot;&gt;1 000 символов — ищем верхнюю границу, если она есть. Заодно смотрим, как это выглядит в интерфейсе и корректируем тест.&lt;/p&gt;
  &lt;p id=&quot;Kred&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;JNXs&quot;&gt;1 000 000 символов — ищем технологическую границу&lt;/p&gt;
  &lt;p id=&quot;yuaq&quot;&gt;Ошибка 400 — «Имя слишком длинное. Максимальная длина (такая-то)»&lt;/p&gt;
  &lt;p id=&quot;6Huv&quot;&gt;&lt;strong&gt;Параметр password&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;i5cp&quot;&gt;Обычный пароль типа 1&lt;/p&gt;
  &lt;p id=&quot;tiLJ&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;n7du&quot;&gt;Разный регистр, буквы и спецсимволы:&lt;/p&gt;
  &lt;p id=&quot;M9df&quot;&gt;Mixa1234567890&amp;#x60;-=[]\;’/.,~!@#$%^&amp;amp;*()_+}{:”?&amp;gt;&amp;lt;|Ё_+ХЪ/ЖЭБЮ,ёхъ\-=.&lt;/p&gt;
  &lt;p id=&quot;p8Jz&quot;&gt;Успешный запрос&lt;/p&gt;
  &lt;p id=&quot;i9PH&quot;&gt;1 000 символов — ищем верхнюю границу, если она есть. Заодно смотрим, как это выглядит в интерфейсе и корректируем тест.&lt;/p&gt;
  &lt;p id=&quot;nLQE&quot;&gt;Успешный запрос, пароль обрезается до X символов&lt;/p&gt;
  &lt;p id=&quot;VxdA&quot;&gt;1 000 000 символов — ищем технологическую границу&lt;/p&gt;
  &lt;p id=&quot;HLJq&quot;&gt;Успешный запрос, пароль обрезается до X символов&lt;/p&gt;
  &lt;p id=&quot;39n9&quot;&gt;&lt;strong&gt;Тело сообщения (body)&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;oAT5&quot;&gt;Перестановка мест слагаемых в json&lt;/p&gt;
  &lt;p id=&quot;nY9T&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;FuIX&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;kWVa&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.com&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;Bci7&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;7ikM&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;x2ci&quot;&gt;Статус 200, корректный ответ&lt;/p&gt;
  &lt;p id=&quot;KwDJ&quot;&gt;Перестановка мест слагаемых в form-data&lt;/p&gt;
  &lt;p id=&quot;oehb&quot;&gt;Статус 200, корректный ответ&lt;/p&gt;
  &lt;p id=&quot;UL4C&quot;&gt;Меняем регистр у любого параметра:&lt;/p&gt;
  &lt;p id=&quot;Tg4Z&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;Jst0&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.com&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;im3T&quot;&gt;&amp;quot;NAME&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;o2tF&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;B2e3&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;Qu9d&quot;&gt;Статус 200, корректный ответ&lt;/p&gt;
  &lt;p id=&quot;BTHU&quot;&gt;Меняем в запросе тип метода с POST на GET&lt;/p&gt;
  &lt;p id=&quot;iNRp&quot;&gt;Статус 400, ошибка «Неправильный тип метода, нужно использовать POST»&lt;/p&gt;
  &lt;p id=&quot;4OeR&quot;&gt;&lt;strong&gt;Well formed json&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;wlFB&quot;&gt;Запятая после последней пары «ключ:значение»:&lt;/p&gt;
  &lt;p id=&quot;qcKH&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;yJhC&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mailcom&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;fWp5&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;HPjH&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;89yi&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;Frhs&quot;&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;Neu5&quot;&gt;В теле ошибка: &amp;quot;Не well formed json в запросе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;cepl&quot;&gt;Запрос не в виде пар “ключ:значение”, у пароля убираем значение:&lt;/p&gt;
  &lt;p id=&quot;MgO9&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;Ue0s&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.com&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;oxR5&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;U2Wc&quot;&gt;&amp;quot;password&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;Dqnw&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;MjDr&quot;&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;XcgG&quot;&gt;В теле ошибка: &amp;quot;Не well formed json в запросе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;kLEh&quot;&gt;Данные не разделены запятыми&lt;/p&gt;
  &lt;p id=&quot;TpmJ&quot;&gt;{&lt;/p&gt;
  &lt;p id=&quot;Kx0C&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.com&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;bv1Z&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;Juja&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;u3Hh&quot;&gt;}&lt;/p&gt;
  &lt;p id=&quot;jhFj&quot;&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;IhQy&quot;&gt;В теле ошибка: &amp;quot;Не well formed json в запросе&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;YjYD&quot;&gt;объект в квадратных скобках, а не фигурных&lt;/p&gt;
  &lt;p id=&quot;y5kQ&quot;&gt;[&lt;/p&gt;
  &lt;p id=&quot;W4nI&quot;&gt;&amp;quot;email&amp;quot;: &amp;quot;test&lt;em&gt;{{$randomInt}}&lt;/em&gt;@mail.com&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;9x0E&quot;&gt;&amp;quot;name&amp;quot;: &amp;quot; Машенька&lt;em&gt;{{$randomInt}}&lt;/em&gt;&amp;quot;,&lt;/p&gt;
  &lt;p id=&quot;POLy&quot;&gt;&amp;quot;password&amp;quot;: &amp;quot;1&amp;quot;&lt;/p&gt;
  &lt;p id=&quot;fPPt&quot;&gt;]&lt;/p&gt;
  &lt;p id=&quot;kO9b&quot;&gt;Статус 400&lt;/p&gt;
  &lt;p id=&quot;mb2G&quot;&gt;В теле ошибка: &amp;quot;Не well formed json в запросе&amp;quot;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;5T89&quot;&gt;Вывод&lt;/h2&gt;
  &lt;p id=&quot;ihnF&quot;&gt;Тестирование API — это не страшно! По факту это всё то же самое, что в GUI + дополнительные тесты. В интерфейсе нельзя подвигать местами поля или изменить название поля. А в API можно.&lt;/p&gt;
  &lt;p id=&quot;OV8w&quot;&gt;Но всегда в первую очередь важен тест-дизайн. Прочитайте ТЗ и проверьте его, учитывая классы эквивалентности и граничные значения. А потом добавьте API-часть:&lt;/p&gt;
  &lt;ul id=&quot;qywc&quot;&gt;
    &lt;li id=&quot;5FFb&quot;&gt;Перестановка мест слагаемых в json&lt;/li&gt;
    &lt;li id=&quot;fuKH&quot;&gt;Перестановка мест слагаемых в form-data&lt;/li&gt;
    &lt;li id=&quot;2NRd&quot;&gt;Регистрозависимость&lt;/li&gt;
    &lt;li id=&quot;kbUu&quot;&gt;Другой тип метода&lt;/li&gt;
    &lt;li id=&quot;nYL0&quot;&gt;Well formed json / xml&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>maya.work905:TPNHgOwh-d2</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/TPNHgOwh-d2?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>JSON</title><published>2025-10-20T08:03:40.258Z</published><updated>2025-11-25T14:43:39.966Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/fd/50/fd501bb9-145b-4703-a9b3-12a902243824.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/d3/d6/d3d67bc8-82bc-42a2-8001-413472928f01.jpeg&quot;&gt;Что такое JSON?</summary><content type="html">
  &lt;figure id=&quot;fYpd&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d3/d6/d3d67bc8-82bc-42a2-8001-413472928f01.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;NOqH&quot;&gt;&lt;a href=&quot;https://webref.ru/dev/json-tutorial&quot; target=&quot;_blank&quot;&gt;Что такое JSON?&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;EyEW&quot;&gt;&lt;a href=&quot;https://webref.ru/dev/json-tutorial/json-syntax&quot; target=&quot;_blank&quot;&gt;Синтаксис JSON-объекта&lt;/a&gt;: как отделяется ключ от значения, как отделяются пары ключ-значение друг от друга&lt;/p&gt;
  &lt;p id=&quot;9xwy&quot;&gt;&lt;a href=&quot;https://webref.ru/dev/json-tutorial/json-data-types&quot; target=&quot;_blank&quot;&gt;Какие типы данных&lt;/a&gt; есть в JSON?&lt;/p&gt;
  &lt;p id=&quot;pDr1&quot;&gt;Какие типы данных берутся в кавычки, а какие нет?&lt;/p&gt;
  &lt;h2 id=&quot;ru4G&quot;&gt;🗂️ 1. Что такое JSON&lt;/h2&gt;
  &lt;p id=&quot;uzLU&quot;&gt;&lt;strong&gt;JSON (JavaScript Object Notation)&lt;/strong&gt; — это простой текстовый формат, который используют для обмена данными между программами.&lt;/p&gt;
  &lt;p id=&quot;5npR&quot;&gt;📦 Он хранит информацию в виде пар «имя: значение».&lt;br /&gt;Благодаря этому JSON легко читается как человеком, так и компьютером.&lt;/p&gt;
  &lt;p id=&quot;B0pJ&quot;&gt;💡 Пример:&lt;/p&gt;
  &lt;pre id=&quot;k1GL&quot;&gt;{ &amp;quot;name&amp;quot;: &amp;quot;Alice&amp;quot;, &amp;quot;age&amp;quot;: 25 }
&lt;/pre&gt;
  &lt;p id=&quot;O9Ag&quot;&gt;📘 Применение:&lt;/p&gt;
  &lt;ul id=&quot;1NqJ&quot;&gt;
    &lt;li id=&quot;KAC8&quot;&gt;передача данных между браузером и сервером;&lt;/li&gt;
    &lt;li id=&quot;NkBf&quot;&gt;хранение настроек и информации о пользователях.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;gjwi&quot;&gt;🧱  2. Объекты JSON&lt;/h2&gt;
  &lt;p id=&quot;MDtC&quot;&gt;&lt;strong&gt;Объект JSON&lt;/strong&gt; — это набор пар «имя: значение», заключённый в фигурные скобки &lt;code&gt;{ }&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;yDHL&quot;&gt;📗 Пример:&lt;/p&gt;
  &lt;pre id=&quot;xg0T&quot;&gt;{
  &amp;quot;artistname&amp;quot;: &amp;quot;Deep Purple&amp;quot;,
  &amp;quot;formed&amp;quot;: &amp;quot;1968&amp;quot;,
  &amp;quot;origin&amp;quot;: &amp;quot;Хертфорд, Великобритания&amp;quot;
}
&lt;/pre&gt;
  &lt;p id=&quot;FaiP&quot;&gt;🧩 Каждое имя (ключ) записывается в кавычках, после него ставится двоеточие и значение.&lt;br /&gt;Значением может быть:&lt;/p&gt;
  &lt;ul id=&quot;8emM&quot;&gt;
    &lt;li id=&quot;gK9B&quot;&gt;строка &lt;code&gt;&amp;quot;text&amp;quot;&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;LCdD&quot;&gt;число &lt;code&gt;123&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;nyHD&quot;&gt;логическое значение &lt;code&gt;true / false&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;Xe2P&quot;&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;2wnL&quot;&gt;другой объект &lt;code&gt;{...}&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;NCTy&quot;&gt;массив &lt;code&gt;[...]&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Edgo&quot;&gt;📋  3. Массивы JSON&lt;/h2&gt;
  &lt;p id=&quot;QWWx&quot;&gt;&lt;strong&gt;Массив JSON&lt;/strong&gt; — это упорядоченный список значений, заключённый в квадратные скобки &lt;code&gt;[ ]&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;7l4I&quot;&gt;💡 Пример:&lt;/p&gt;
  &lt;pre id=&quot;CrLd&quot;&gt;{
  &amp;quot;artists&amp;quot;: [
    { &amp;quot;artistname&amp;quot;: &amp;quot;Deep Purple&amp;quot;, &amp;quot;formed&amp;quot;: &amp;quot;1968&amp;quot; },
    { &amp;quot;artistname&amp;quot;: &amp;quot;Maroon 5&amp;quot;, &amp;quot;formed&amp;quot;: &amp;quot;1994&amp;quot; }
  ]
}
&lt;/pre&gt;
  &lt;p id=&quot;67zq&quot;&gt;📘 Массив может содержать строки, числа, объекты или даже другие массивы.&lt;br /&gt;Он нужен, когда нужно хранить &lt;strong&gt;список похожих элементов&lt;/strong&gt;, например пользователей, песни, товары и т.д.&lt;/p&gt;
  &lt;p id=&quot;92du&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;wG20&quot;&gt;4. Типы данных в JSON&lt;/h2&gt;
  &lt;p id=&quot;Rj2E&quot;&gt;В JSON есть 6 типов данных:&lt;/p&gt;
  &lt;p id=&quot;Ru23&quot;&gt;Тип&lt;/p&gt;
  &lt;p id=&quot;WiKP&quot;&gt;Пример&lt;/p&gt;
  &lt;p id=&quot;WsdB&quot;&gt;Описание&lt;/p&gt;
  &lt;p id=&quot;m4yU&quot;&gt;🧩 &lt;strong&gt;Строка&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;oiHX&quot;&gt;&lt;code&gt;&amp;quot;Hello&amp;quot;&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;up8b&quot;&gt;Текст в двойных кавычках&lt;/p&gt;
  &lt;p id=&quot;VUWk&quot;&gt;🔢 &lt;strong&gt;Число&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;HPIB&quot;&gt;&lt;code&gt;42&lt;/code&gt;, &lt;code&gt;-5&lt;/code&gt;, &lt;code&gt;0.5&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;ADEk&quot;&gt;Целое, дробное или отрицательное число&lt;/p&gt;
  &lt;p id=&quot;1wZh&quot;&gt;⚖️ &lt;strong&gt;Логический&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;ZTiV&quot;&gt;&lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;RX9M&quot;&gt;Истина или ложь&lt;/p&gt;
  &lt;p id=&quot;kOAm&quot;&gt;🚫 &lt;strong&gt;Null&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;xVpO&quot;&gt;&lt;code&gt;null&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;h29c&quot;&gt;Пустое значение&lt;/p&gt;
  &lt;p id=&quot;o270&quot;&gt;🧱 &lt;strong&gt;Объект&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;ZQEs&quot;&gt;&lt;code&gt;{ &amp;quot;name&amp;quot;: &amp;quot;Bob&amp;quot; }&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;va3I&quot;&gt;Набор пар «имя: значение»&lt;/p&gt;
  &lt;p id=&quot;vFMn&quot;&gt;📋 &lt;strong&gt;Массив&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;yYfv&quot;&gt;&lt;code&gt;[1, 2, 3]&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;6PZy&quot;&gt;Упорядоченный список значений&lt;/p&gt;
  &lt;p id=&quot;aQ0D&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;OJOY&quot;&gt;5. Вложенные данные&lt;/h2&gt;
  &lt;p id=&quot;XN0q&quot;&gt;JSON может содержать &lt;strong&gt;объекты внутри объектов&lt;/strong&gt; и &lt;strong&gt;массивы внутри массивов&lt;/strong&gt;.&lt;br /&gt;Это позволяет создавать сложные структуры данных.&lt;/p&gt;
  &lt;p id=&quot;Lz6M&quot;&gt;💡 Пример:&lt;/p&gt;
  &lt;pre id=&quot;kvOY&quot;&gt;{
  &amp;quot;artist&amp;quot;: {
    &amp;quot;name&amp;quot;: &amp;quot;Deep Purple&amp;quot;,
    &amp;quot;albums&amp;quot;: [
      { &amp;quot;title&amp;quot;: &amp;quot;Machine Head&amp;quot;, &amp;quot;year&amp;quot;: 1972 },
      { &amp;quot;title&amp;quot;: &amp;quot;Stormbringer&amp;quot;, &amp;quot;year&amp;quot;: 1974 }
    ]
  }
}
&lt;/pre&gt;
  &lt;p id=&quot;6rQO&quot;&gt;📘 Здесь у исполнителя есть список альбомов, и каждый альбом хранит свои данные.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;CbcX&quot;&gt;🧾  6. Пробелы и форматирование&lt;/h2&gt;
  &lt;p id=&quot;t6rZ&quot;&gt;JSON &lt;strong&gt;не чувствителен к пробелам и переносам строк&lt;/strong&gt;.&lt;br /&gt;Главное — правильные кавычки, запятые и скобки.&lt;/p&gt;
  &lt;p id=&quot;v4Jk&quot;&gt;💡 Оба примера ниже абсолютно одинаковы:&lt;/p&gt;
  &lt;pre id=&quot;jrAx&quot;&gt;{ &amp;quot;name&amp;quot;: &amp;quot;Alice&amp;quot;, &amp;quot;age&amp;quot;: 25 }
&lt;/pre&gt;
  &lt;pre id=&quot;KlzR&quot;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;Alice&amp;quot;,
  &amp;quot;age&amp;quot;: 25
}
&lt;/pre&gt;
  &lt;p id=&quot;rd2I&quot;&gt;✅ Пробелы можно использовать для читаемости,&lt;br /&gt;⚠️ но если добавить пробел внутри кавычек — это уже часть данных.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;lRVQ&quot;&gt;⚠️  7. Экранирование символов&lt;/h2&gt;
  &lt;figure id=&quot;SA1y&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ee/59/ee5904c8-aadc-47e6-9907-a720d31ed0cf.jpeg&quot; width=&quot;1024&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;PoyQ&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;fhnp&quot;&gt;Некоторые символы в JSON нужно &lt;strong&gt;экранировать&lt;/strong&gt; — то есть писать с &lt;code&gt;\&lt;/code&gt;, чтобы не нарушить синтаксис.&lt;/p&gt;
  &lt;p id=&quot;ZvlP&quot;&gt;📋 Например:&lt;/p&gt;
  &lt;pre id=&quot;Wyer&quot;&gt;{ &amp;quot;quote&amp;quot;: &amp;quot;Он сказал: \&amp;quot;Привет!\&amp;quot;&amp;quot; }
&lt;/pre&gt;
  &lt;p id=&quot;yoW8&quot;&gt;🧠 Часто используемые варианты:&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;Npsn&quot;&gt;&lt;/h1&gt;
  &lt;figure id=&quot;7l9U&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f0/bb/f0bb9893-5580-4255-8867-b27e87763c14.png&quot; width=&quot;1440&quot; /&gt;
  &lt;/figure&gt;
  &lt;section&gt;
    &lt;p id=&quot;ZbMD&quot;&gt;Вы также можете использовать шестнадцатеричный эквивалент для экранирования символа, например, \u002f или \u002F для представления символа косой черты.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;1y6u&quot;&gt;Загляни еще сюда для наглядности&lt;/p&gt;
  &lt;figure id=&quot;9drI&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/gi60w7B76d4?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;nr3f&quot;&gt;И почитать вот тут: &lt;a href=&quot;https://habr.com/ru/articles/554274/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/articles/554274/&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:QlRcqyrNxgZ</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/QlRcqyrNxgZ?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Devtools - главный инструмент тестировщика</title><published>2025-10-20T07:54:32.711Z</published><updated>2025-11-26T14:23:31.756Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/24/32/2432ce85-6a72-4f51-83c5-f99c375325fe.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/64/72/64729f36-06a0-4dc8-94d1-77300ba50b2c.jpeg&quot;&gt;DevTools (Developer Tools) — это встроенный в браузер (например, Google Chrome) набор инструментов для разработчиков и тестировщиков.</summary><content type="html">
  &lt;h2 id=&quot;8ya4&quot;&gt;1. Что такое DevTools и как с ним работать&lt;/h2&gt;
  &lt;figure id=&quot;m79d&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/64/72/64729f36-06a0-4dc8-94d1-77300ba50b2c.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;DP7G&quot;&gt;&lt;strong&gt;DevTools&lt;/strong&gt; (Developer Tools) — это встроенный в браузер (например, Google Chrome) набор инструментов для разработчиков и тестировщиков.&lt;/p&gt;
  &lt;p id=&quot;dzXT&quot;&gt;С его помощью можно:&lt;/p&gt;
  &lt;ul id=&quot;vOyL&quot;&gt;
    &lt;li id=&quot;EZgW&quot;&gt;смотреть &lt;strong&gt;HTML и CSS&lt;/strong&gt; страницы 🧱&lt;/li&gt;
    &lt;li id=&quot;NGBm&quot;&gt;отслеживать &lt;strong&gt;запросы к серверу&lt;/strong&gt; 🌐&lt;/li&gt;
    &lt;li id=&quot;FFb8&quot;&gt;проверять &lt;strong&gt;ошибки в консоли&lt;/strong&gt; ⚠️&lt;/li&gt;
    &lt;li id=&quot;uzR2&quot;&gt;смотреть и чистить &lt;strong&gt;куки, кэш, localStorage&lt;/strong&gt; 🍪&lt;/li&gt;
    &lt;li id=&quot;fVYa&quot;&gt;эмулировать &lt;strong&gt;медленный интернет, мобильный экран&lt;/strong&gt; 📱&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;n1vb&quot;&gt;👉 &lt;strong&gt;Совет:&lt;/strong&gt;&lt;br /&gt;Когда читаешь этот разбор, &lt;strong&gt;открывай DevTools и кликай параллельно.&lt;/strong&gt; Так информация лучше «приклеится».&lt;/p&gt;
  &lt;p id=&quot;KgBq&quot;&gt;Открыть DevTools в Chrome:&lt;/p&gt;
  &lt;ul id=&quot;ViMs&quot;&gt;
    &lt;li id=&quot;NYpC&quot;&gt;Windows: &lt;code&gt;F12&lt;/code&gt; или &lt;code&gt;Ctrl + Shift + I&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;iYQE&quot;&gt;Mac: &lt;code&gt;Cmd + Option + I&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;1oFg&quot;&gt;2. Основные вкладки DevTools и зачем они тестировщику&lt;/h2&gt;
  &lt;p id=&quot;OEEi&quot;&gt;Нам как тестировщику &lt;strong&gt;не нужно&lt;/strong&gt; знать &lt;em&gt;всё&lt;/em&gt; на уровне разработчика.&lt;br /&gt;Обычно в работе ты реально будешь использовать &lt;strong&gt;10–20% возможностей&lt;/strong&gt;, но:&lt;/p&gt;
  &lt;ul id=&quot;YU84&quot;&gt;
    &lt;li id=&quot;B4LC&quot;&gt;на &lt;strong&gt;собесах&lt;/strong&gt; часто спрашивают: «Что ты делаешь во вкладке Network/Elements/Console?»&lt;/li&gt;
    &lt;li id=&quot;t8G9&quot;&gt;в реальной работе это даёт тебе &lt;strong&gt;+100 к полезности&lt;/strong&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;TtCE&quot;&gt;Ниже пойдём по вкладкам.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;stYB&quot;&gt;🔹 Elements — «Разметка и стили страницы»&lt;/h2&gt;
  &lt;p id=&quot;oZPl&quot;&gt;&lt;strong&gt;Что отображается на вкладке Elements?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Hhgp&quot;&gt;Вкладка &lt;strong&gt;Elements&lt;/strong&gt; показывает:&lt;/p&gt;
  &lt;ul id=&quot;6FvI&quot;&gt;
    &lt;li id=&quot;d7oz&quot;&gt;структуру страницы (HTML / DOM-дерево),&lt;/li&gt;
    &lt;li id=&quot;XLMN&quot;&gt;применённые стили (CSS),&lt;/li&gt;
    &lt;li id=&quot;vERu&quot;&gt;события, свойства, и т.д.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Tvhd&quot;&gt;Проще говоря:&lt;br /&gt;👉 &lt;strong&gt;Это «скелет» страницы + «одежда» (стили).&lt;/strong&gt;&lt;/p&gt;
  &lt;h3 id=&quot;etlR&quot;&gt;Что можно делать тестировщику в Elements?&lt;/h3&gt;
  &lt;ul id=&quot;y5zb&quot;&gt;
    &lt;li id=&quot;s1qS&quot;&gt;Смотреть, &lt;strong&gt;из чего состоит элемент&lt;/strong&gt;: текст, теги, атрибуты&lt;/li&gt;
    &lt;li id=&quot;3pTe&quot;&gt;Проверять, &lt;strong&gt;почему что-то съехало&lt;/strong&gt;: отступы, размеры, шрифты&lt;/li&gt;
    &lt;li id=&quot;yYi4&quot;&gt;Временно &lt;strong&gt;менять текст/стили&lt;/strong&gt;, чтобы проверить гипотезу&lt;br /&gt;(например, если текст лезет за границы блока — «а что, если уменьшить шрифт?»)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;NF8v&quot;&gt;Полезные вещи:&lt;/h3&gt;
  &lt;ul id=&quot;7FLO&quot;&gt;
    &lt;li id=&quot;NOEW&quot;&gt;🔍 &lt;strong&gt;Выбор элемента курсором&lt;/strong&gt;&lt;br /&gt;В левом верхнем углу DevTools есть иконка стрелочки.&lt;br /&gt;Нажимаешь её — потом кликаешь по любому элементу на странице — и DevTools сразу показывают HTML этого элемента.&lt;/li&gt;
    &lt;li id=&quot;HSbm&quot;&gt;🎨 Вкладка &lt;strong&gt;Styles&lt;/strong&gt; справа&lt;br /&gt;Показывает &lt;strong&gt;все CSS-правила&lt;/strong&gt;, которые действуют на выбранный элемент:&lt;/li&gt;
    &lt;ul id=&quot;OhHq&quot;&gt;
      &lt;li id=&quot;QXIs&quot;&gt;применённые&lt;/li&gt;
      &lt;li id=&quot;T7uN&quot;&gt;перечёркнутые (переопределены более сильным правилом)&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;bSnN&quot;&gt;⚡ Вкладки:&lt;/li&gt;
    &lt;ul id=&quot;Sdcj&quot;&gt;
      &lt;li id=&quot;bzLJ&quot;&gt;&lt;strong&gt;Event Listeners&lt;/strong&gt; — какие события повешены на элемент (click, input и т.п.)&lt;/li&gt;
      &lt;li id=&quot;Gs1i&quot;&gt;&lt;strong&gt;DOM Breakpoints&lt;/strong&gt; — точки останова (чаще нужно девам)&lt;/li&gt;
      &lt;li id=&quot;Kq5I&quot;&gt;&lt;strong&gt;Properties&lt;/strong&gt; — свойства элемента&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;9OjT&quot;&gt;🔹 Console — «Ошибки и сообщения от кода»&lt;/h2&gt;
  &lt;p id=&quot;qYGj&quot;&gt;&lt;strong&gt;Что полезного тестировщик может увидеть во вкладке Console?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;BADA&quot;&gt;Вкладка &lt;strong&gt;Console&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;63rr&quot;&gt;
    &lt;li id=&quot;Rq2z&quot;&gt;показывает &lt;strong&gt;ошибки JavaScript&lt;/strong&gt; (которые ломают функционал) ⚠️&lt;/li&gt;
    &lt;li id=&quot;Yv0r&quot;&gt;предупреждения (warnings)&lt;/li&gt;
    &lt;li id=&quot;qNTg&quot;&gt;любые &lt;strong&gt;лог-сообщения&lt;/strong&gt;, которые разработчик вывел через &lt;code&gt;console.log()&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;gv0M&quot;&gt;иногда сюда выводят &lt;strong&gt;XHR / fetch запросы&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;3Hrk&quot;&gt;Для тестировщика это:&lt;/p&gt;
  &lt;ul id=&quot;aAb1&quot;&gt;
    &lt;li id=&quot;7z42&quot;&gt;быстрый способ понять:&lt;br /&gt;«Почему кнопка не работает? А, там ошибка JS…»&lt;/li&gt;
    &lt;li id=&quot;aqUi&quot;&gt;аргумент в споре:&lt;br /&gt;«Смотри, при этом действии в консоли ошибка, это явно баг».&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ry69&quot;&gt;Полезные вещи:&lt;/p&gt;
  &lt;ul id=&quot;FUrD&quot;&gt;
    &lt;li id=&quot;gh7q&quot;&gt;можно &lt;strong&gt;фильтровать&lt;/strong&gt; сообщения (ошибки, warning, info)&lt;/li&gt;
    &lt;li id=&quot;Yy27&quot;&gt;можно &lt;strong&gt;очистить консоль&lt;/strong&gt; 🧹&lt;/li&gt;
    &lt;li id=&quot;3f9g&quot;&gt;можно включить &lt;strong&gt;Preserve log&lt;/strong&gt; — чтобы сообщения не очищались при перезагрузке страницы&lt;/li&gt;
    &lt;li id=&quot;KCML&quot;&gt;консоль можно открыть &lt;strong&gt;внизу любой вкладки&lt;/strong&gt; (клавиша &lt;code&gt;Esc&lt;/code&gt;)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;q6sH&quot;&gt;🔹 Sources — «Файлы и отладка кода» (для QA — эпизодически)&lt;/h2&gt;
  &lt;p id=&quot;gd4e&quot;&gt;Вкладка &lt;strong&gt;Sources&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;uOH0&quot;&gt;
    &lt;li id=&quot;EPy9&quot;&gt;показывает &lt;strong&gt;все файлы&lt;/strong&gt;, которые загружены на страницу (JS, HTML, CSS и т.п.)&lt;/li&gt;
    &lt;li id=&quot;uwwY&quot;&gt;можно:&lt;/li&gt;
    &lt;ul id=&quot;EP9A&quot;&gt;
      &lt;li id=&quot;BlwA&quot;&gt;открыть файл&lt;/li&gt;
      &lt;li id=&quot;6BB0&quot;&gt;посмотреть код&lt;/li&gt;
      &lt;li id=&quot;HqnQ&quot;&gt;поставить &lt;strong&gt;брейкпоинт&lt;/strong&gt; (точку остановки)&lt;/li&gt;
      &lt;li id=&quot;ROsD&quot;&gt;дебажить шаг за шагом&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;PkrO&quot;&gt;Для начинающего тестировщика &lt;strong&gt;часто это не обязательно&lt;/strong&gt;, если ты не лезешь в сложную отладку.&lt;/p&gt;
  &lt;p id=&quot;WItE&quot;&gt;Но понимать идею полезно:&lt;/p&gt;
  &lt;ul id=&quot;KFbW&quot;&gt;
    &lt;li id=&quot;ulgA&quot;&gt;если разработчик говорит: «Поставь брейкпоинт и глянь параметр» — уже не будет паники 😄&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;ZQlf&quot;&gt;🔹 Network — «Все запросы к серверу» 🌐&lt;/h2&gt;
  &lt;p id=&quot;Zor8&quot;&gt;Это &lt;strong&gt;одна из самых важных вкладок для тестировщика.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;N881&quot;&gt;&lt;strong&gt;Что полезного для тестировщика есть во вкладке Network?&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;FEX4&quot;&gt;
    &lt;li id=&quot;qhCD&quot;&gt;список &lt;strong&gt;всех HTTP-запросов&lt;/strong&gt;, которые отправляет страница&lt;/li&gt;
    &lt;li id=&quot;TZXr&quot;&gt;по каждому запросу можно узнать:&lt;/li&gt;
    &lt;ul id=&quot;tTFW&quot;&gt;
      &lt;li id=&quot;eLOb&quot;&gt;URL&lt;/li&gt;
      &lt;li id=&quot;zC01&quot;&gt;метод (GET, POST и т.п.)&lt;/li&gt;
      &lt;li id=&quot;eVIZ&quot;&gt;статус-код (200, 400, 500 и т.п.)&lt;/li&gt;
      &lt;li id=&quot;M72d&quot;&gt;время выполнения&lt;/li&gt;
      &lt;li id=&quot;0xb8&quot;&gt;&lt;strong&gt;тело запроса (Request)&lt;/strong&gt;&lt;/li&gt;
      &lt;li id=&quot;R584&quot;&gt;&lt;strong&gt;ответ (Response)&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;wfJR&quot;&gt;🕒 Где посмотреть, как долго выполнялся HTTP-запрос?&lt;/h3&gt;
  &lt;ol id=&quot;mLNM&quot;&gt;
    &lt;li id=&quot;DNJd&quot;&gt;Открой вкладку &lt;strong&gt;Network&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;VMUg&quot;&gt;Обнови страницу (F5) — увидишь таблицу запросов&lt;/li&gt;
    &lt;li id=&quot;Li7u&quot;&gt;Кликни по нужному запросу&lt;/li&gt;
    &lt;li id=&quot;UQ76&quot;&gt;Перейди во вкладку &lt;strong&gt;Timing&lt;/strong&gt;&lt;br /&gt;Там видно:&lt;/li&gt;
    &lt;ul id=&quot;W6YZ&quot;&gt;
      &lt;li id=&quot;rGOD&quot;&gt;сколько времени занял запрос,&lt;/li&gt;
      &lt;li id=&quot;j4Kv&quot;&gt;где были задержки (DNS, SSL, Waiting и т.п.).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;7ioP&quot;&gt;📦 Где посмотреть тело запроса и ответ?&lt;/h3&gt;
  &lt;ol id=&quot;sVwI&quot;&gt;
    &lt;li id=&quot;fDNe&quot;&gt;Выбрать запрос в списке&lt;/li&gt;
    &lt;li id=&quot;Yr3Z&quot;&gt;В правой части:&lt;/li&gt;
    &lt;ul id=&quot;hcAE&quot;&gt;
      &lt;li id=&quot;uFMk&quot;&gt;вкладка &lt;strong&gt;Headers&lt;/strong&gt; — общая инфа (URL, метод, код ответа)&lt;/li&gt;
      &lt;li id=&quot;BHhF&quot;&gt;вкладка &lt;strong&gt;Payload&lt;/strong&gt; / &lt;strong&gt;Request Body&lt;/strong&gt; — тело запроса (что мы отправили на сервер)&lt;/li&gt;
      &lt;li id=&quot;CcoQ&quot;&gt;вкладка &lt;strong&gt;Response&lt;/strong&gt; — тело ответа (что вернул сервер)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;53K5&quot;&gt;Это супер полезно при &lt;strong&gt;тестировании API через UI&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;KGht&quot;&gt;
    &lt;li id=&quot;V2pl&quot;&gt;«Я отправила такие данные — а сервер ответил вот этим»&lt;/li&gt;
    &lt;li id=&quot;c0E3&quot;&gt;«В UI ошибка, но в ответе от сервера всё ок — баг фронта»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;rqZf&quot;&gt;🚦 Имитация медленного интернета&lt;/h3&gt;
  &lt;p id=&quot;KpxL&quot;&gt;&lt;strong&gt;Как включить имитацию медленного интернета?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;9iFn&quot;&gt;На вкладке &lt;strong&gt;Network&lt;/strong&gt; сверху есть поле &lt;strong&gt;Throttling&lt;/strong&gt;.&lt;/p&gt;
  &lt;ul id=&quot;SGqh&quot;&gt;
    &lt;li id=&quot;t8lT&quot;&gt;Там можно выбрать:&lt;/li&gt;
    &lt;ul id=&quot;SeLe&quot;&gt;
      &lt;li id=&quot;x4Qw&quot;&gt;Online (без ограничения)&lt;/li&gt;
      &lt;li id=&quot;UTny&quot;&gt;Slow 3G&lt;/li&gt;
      &lt;li id=&quot;h5s0&quot;&gt;Fast 3G&lt;/li&gt;
      &lt;li id=&quot;tV93&quot;&gt;Offline (полностью без сети)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Oe2r&quot;&gt;Это помогает протестировать:&lt;/p&gt;
  &lt;ul id=&quot;BYwL&quot;&gt;
    &lt;li id=&quot;TesU&quot;&gt;как ведёт себя сайт при &lt;strong&gt;медленном интернете&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;lQpf&quot;&gt;корректно ли отображается &lt;strong&gt;лоудер / спиннер / сообщения о проблемах с сетью&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;hPj3&quot;&gt;💾 Отключение кэша&lt;/h3&gt;
  &lt;p id=&quot;ja1c&quot;&gt;На вкладке &lt;strong&gt;Network&lt;/strong&gt; есть чекбокс &lt;strong&gt;Disable cache&lt;/strong&gt;.&lt;/p&gt;
  &lt;ul id=&quot;W31l&quot;&gt;
    &lt;li id=&quot;f0GQ&quot;&gt;Если включить его — браузер &lt;strong&gt;не будет использовать кэш&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;FJeu&quot;&gt;Важно: это работает &lt;strong&gt;только пока открыт DevTools&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;4c4R&quot;&gt;Это удобно при тестировании:&lt;/p&gt;
  &lt;ul id=&quot;QAD8&quot;&gt;
    &lt;li id=&quot;wfOE&quot;&gt;свежего функционала&lt;/li&gt;
    &lt;li id=&quot;UJd3&quot;&gt;когда нужно убедиться, что подтянулись &lt;strong&gt;новые файлы&lt;/strong&gt;, а не старые из кэша&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;FpNJ&quot;&gt;📊 Итоговая сводка по Network&lt;/h3&gt;
  &lt;p id=&quot;tW4d&quot;&gt;Внизу вкладки Network обычно видно:&lt;/p&gt;
  &lt;ul id=&quot;YF8V&quot;&gt;
    &lt;li id=&quot;GRDA&quot;&gt;количество запросов&lt;/li&gt;
    &lt;li id=&quot;IsPR&quot;&gt;общий объём загруженных данных&lt;/li&gt;
    &lt;li id=&quot;l4vx&quot;&gt;время:&lt;/li&gt;
    &lt;ul id=&quot;aEHF&quot;&gt;
      &lt;li id=&quot;nu9S&quot;&gt;загрузки DOM&lt;/li&gt;
      &lt;li id=&quot;uotm&quot;&gt;полной загрузки страницы&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;7P6D&quot;&gt;Это помогает понять:&lt;/p&gt;
  &lt;blockquote id=&quot;JP5x&quot;&gt;«Почему сайт тормозит? Потому что грузится 5 МБ картинок и 300 запросов.»&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;36JN&quot;&gt;&lt;/h2&gt;
  &lt;p id=&quot;y1rF&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;aqJ1&quot;&gt;🔹 Performance — «Производительность страницы» ⚙️&lt;/h2&gt;
  &lt;p id=&quot;cb1J&quot;&gt;Вкладка &lt;strong&gt;Performance&lt;/strong&gt; показывает:&lt;/p&gt;
  &lt;ul id=&quot;kjxT&quot;&gt;
    &lt;li id=&quot;VvqX&quot;&gt;выполнение JS-кода&lt;/li&gt;
    &lt;li id=&quot;EKWK&quot;&gt;загрузку ресурсов&lt;/li&gt;
    &lt;li id=&quot;3GpE&quot;&gt;FPS&lt;/li&gt;
    &lt;li id=&quot;gVHU&quot;&gt;загрузку CPU&lt;/li&gt;
    &lt;li id=&quot;339r&quot;&gt;задержки анимаций&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;0RiQ&quot;&gt;Обычно её используют:&lt;/p&gt;
  &lt;ul id=&quot;qaYW&quot;&gt;
    &lt;li id=&quot;OvRz&quot;&gt;чтобы анализировать, &lt;strong&gt;почему страница тормозит&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;c6D5&quot;&gt;чтобы понять, где узкие места&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;9gks&quot;&gt;Для начинающего тестировщика:&lt;br /&gt;можно пока знать, &lt;strong&gt;что она существует&lt;/strong&gt;, и что это про &lt;strong&gt;производительность&lt;/strong&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Zywj&quot;&gt;🔹 Memory / JavaScript Profiler — «Память и нагрузка» 🧠&lt;/h2&gt;
  &lt;p id=&quot;YRa4&quot;&gt;Эти вкладки используют для:&lt;/p&gt;
  &lt;ul id=&quot;9iS8&quot;&gt;
    &lt;li id=&quot;GoVm&quot;&gt;поиска &lt;strong&gt;утечек памяти&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;1nJd&quot;&gt;анализа, какие объекты «зависают» и не освобождаются&lt;/li&gt;
    &lt;li id=&quot;yvq0&quot;&gt;профилирования работы JS-кода по CPU&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;jBZH&quot;&gt;Для ручного тестировщика-джуна это &lt;strong&gt;не базовый навык&lt;/strong&gt;, но круто, если хотя бы:&lt;/p&gt;
  &lt;ul id=&quot;shi6&quot;&gt;
    &lt;li id=&quot;aWWg&quot;&gt;знаешь, что Memory — про память и утечки&lt;/li&gt;
    &lt;li id=&quot;9okJ&quot;&gt;JS Profiler — про нагрузку на процессор&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;oKKO&quot;&gt;🔹 Application — «Хранилища, кэш, куки, данные сайта» 📦&lt;/h2&gt;
  &lt;p id=&quot;jkaT&quot;&gt;Это &lt;strong&gt;очень полезная вкладка для тестировщика.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;D2Oa&quot;&gt;&lt;strong&gt;Что можно посмотреть во вкладке Application?&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;GcgI&quot;&gt;
    &lt;li id=&quot;390u&quot;&gt;&lt;strong&gt;Cookies&lt;/strong&gt; — куки сайта 🍪&lt;/li&gt;
    &lt;li id=&quot;BEnK&quot;&gt;&lt;strong&gt;Local Storage&lt;/strong&gt; и &lt;strong&gt;Session Storage&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;nPXC&quot;&gt;&lt;strong&gt;IndexedDB&lt;/strong&gt;, Web SQL&lt;/li&gt;
    &lt;li id=&quot;uqc4&quot;&gt;&lt;strong&gt;кэш приложения&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;jYfw&quot;&gt;шрифты, картинки и т.д.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;PD5g&quot;&gt;🧼 Как очистить данные сайта через DevTools?&lt;/h3&gt;
  &lt;p id=&quot;LuZF&quot;&gt;Вкладка &lt;strong&gt;Application&lt;/strong&gt; → обычно слева есть раздел &lt;strong&gt;&amp;quot;Clear storage&amp;quot;&lt;/strong&gt; (или аналог):&lt;/p&gt;
  &lt;ul id=&quot;U5z7&quot;&gt;
    &lt;li id=&quot;AtOf&quot;&gt;там можно:&lt;/li&gt;
    &lt;ul id=&quot;dRbv&quot;&gt;
      &lt;li id=&quot;yS5N&quot;&gt;очистить &lt;strong&gt;куки&lt;/strong&gt;&lt;/li&gt;
      &lt;li id=&quot;GeUc&quot;&gt;очистить &lt;strong&gt;localStorage&lt;/strong&gt;&lt;/li&gt;
      &lt;li id=&quot;wZQU&quot;&gt;очистить &lt;strong&gt;sessionStorage&lt;/strong&gt;&lt;/li&gt;
      &lt;li id=&quot;RRla&quot;&gt;очистить &lt;strong&gt;кэш&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Kihf&quot;&gt;Либо можно очистить каждый тип данных отдельно:&lt;/p&gt;
  &lt;ul id=&quot;WgL3&quot;&gt;
    &lt;li id=&quot;rDjp&quot;&gt;Cookies → правый клик → Clear all&lt;/li&gt;
    &lt;li id=&quot;yKzn&quot;&gt;Local Storage → очистить конкретные записи&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;sXlw&quot;&gt;Это полезно, когда:&lt;/p&gt;
  &lt;ul id=&quot;Asxu&quot;&gt;
    &lt;li id=&quot;Zu2U&quot;&gt;нужно проверить &lt;strong&gt;поведение «как у нового пользователя»&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;gyWO&quot;&gt;сломалась авторизация и нужно «сбросить состояние»&lt;/li&gt;
    &lt;li id=&quot;2CCY&quot;&gt;что-то закэшировалось и не обновляется&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;mhs2&quot;&gt;❓ Что такое кэш и зачем он нужен?&lt;/h3&gt;
  &lt;p id=&quot;YoWx&quot;&gt;&lt;strong&gt;Кэш&lt;/strong&gt; — это место, где браузер хранит &lt;strong&gt;копии файлов с сайта&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;9ilA&quot;&gt;
    &lt;li id=&quot;CHtm&quot;&gt;картинки&lt;/li&gt;
    &lt;li id=&quot;tvNv&quot;&gt;скрипты&lt;/li&gt;
    &lt;li id=&quot;WR9F&quot;&gt;стили&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;xLfd&quot;&gt;Зачем?&lt;/p&gt;
  &lt;ul id=&quot;ANm4&quot;&gt;
    &lt;li id=&quot;gWOP&quot;&gt;чтобы &lt;strong&gt;ускорить загрузку&lt;/strong&gt; сайта при повторном открытии&lt;/li&gt;
    &lt;li id=&quot;84uR&quot;&gt;не качать одни и те же файлы каждый раз по сети&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;7XhH&quot;&gt;Но для тестировщика это может быть проблемой:&lt;/p&gt;
  &lt;ul id=&quot;9fxf&quot;&gt;
    &lt;li id=&quot;B3e6&quot;&gt;разработчик что-то обновил,&lt;/li&gt;
    &lt;li id=&quot;NHoj&quot;&gt;а ты видишь &lt;strong&gt;старую версию&lt;/strong&gt; из кэша.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;F5Ly&quot;&gt;Поэтому мы иногда &lt;strong&gt;чистим кэш&lt;/strong&gt; или включаем &lt;strong&gt;Disable cache&lt;/strong&gt; в Network.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;gWkO&quot;&gt;❓ Что такое куки и зачем они нужны?&lt;/h3&gt;
  &lt;p id=&quot;rFmL&quot;&gt;&lt;strong&gt;Cookies (куки)&lt;/strong&gt; — это маленькие файлы/записи, которые сайт сохраняет в браузере.&lt;/p&gt;
  &lt;p id=&quot;ET2j&quot;&gt;Обычно в куках хранят:&lt;/p&gt;
  &lt;ul id=&quot;3MQT&quot;&gt;
    &lt;li id=&quot;UcHX&quot;&gt;&lt;strong&gt;сессию пользователя&lt;/strong&gt; (например, токен авторизации)&lt;/li&gt;
    &lt;li id=&quot;iiDj&quot;&gt;настройки (язык, тема)&lt;/li&gt;
    &lt;li id=&quot;b2oh&quot;&gt;иногда данные для аналитики&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;1Wzb&quot;&gt;Для тестировщика куки важны, потому что:&lt;/p&gt;
  &lt;ul id=&quot;zo2P&quot;&gt;
    &lt;li id=&quot;STXH&quot;&gt;если удалить куки — пользователю часто нужно &lt;strong&gt;войти заново&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;46pk&quot;&gt;по кукам можно понять:&lt;/li&gt;
    &lt;ul id=&quot;1648&quot;&gt;
      &lt;li id=&quot;Q7ib&quot;&gt;авторизован ли пользователь&lt;/li&gt;
      &lt;li id=&quot;48y7&quot;&gt;какая у него сессия&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;As6l&quot;&gt;❓ Зачем тестировщику чистить кэш?&lt;/h3&gt;
  &lt;p id=&quot;EYL1&quot;&gt;Иногда:&lt;/p&gt;
  &lt;ul id=&quot;0Zwo&quot;&gt;
    &lt;li id=&quot;ysYt&quot;&gt;у тебя открыта «половина старого кода» или старые стили&lt;/li&gt;
    &lt;li id=&quot;vyAK&quot;&gt;сайт ведёт себя странно&lt;/li&gt;
    &lt;li id=&quot;H6G4&quot;&gt;разработчик говорит: «А у меня всё норм»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;P3Bf&quot;&gt;В таких случаях:&lt;/p&gt;
  &lt;ul id=&quot;Ig7w&quot;&gt;
    &lt;li id=&quot;nRNO&quot;&gt;чистим кэш / включаем Disable cache&lt;/li&gt;
    &lt;li id=&quot;QWGL&quot;&gt;чистим куки, localStorage&lt;/li&gt;
    &lt;li id=&quot;augj&quot;&gt;заново логинимся&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;6JVM&quot;&gt;И проверяем ещё раз — уже на «чистых» данных.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;yhGi&quot;&gt;🔹 Security — «Безопасность и сертификаты» 🔒&lt;/h2&gt;
  &lt;p id=&quot;gHwY&quot;&gt;Вкладка &lt;strong&gt;Security&lt;/strong&gt; показывает:&lt;/p&gt;
  &lt;ul id=&quot;ivvq&quot;&gt;
    &lt;li id=&quot;NFKm&quot;&gt;безопасно ли соединение (HTTPS / не HTTPS)&lt;/li&gt;
    &lt;li id=&quot;6cn6&quot;&gt;какой &lt;strong&gt;сертификат&lt;/strong&gt; используется&lt;/li&gt;
    &lt;li id=&quot;WHyv&quot;&gt;есть ли проблемы с &lt;strong&gt;mixed content&lt;/strong&gt; (когда часть ресурсов грузится по http, часть по https)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;QFvJ&quot;&gt;Тестировщику это может пригодиться:&lt;/p&gt;
  &lt;ul id=&quot;hn1u&quot;&gt;
    &lt;li id=&quot;8NCp&quot;&gt;если задача связана с &lt;strong&gt;безопасностью, SSL, сертификатами&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;jaVY&quot;&gt;если в браузере появляются предупреждения «Сайт небезопасен»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;MTwG&quot;&gt;🔹 Audits (Lighthouse) — «Аудит качества страницы» 🚦&lt;/h2&gt;
  &lt;p id=&quot;avxZ&quot;&gt;Во вкладке &lt;strong&gt;Audits&lt;/strong&gt; (иногда называется &lt;strong&gt;Lighthouse&lt;/strong&gt;) можно:&lt;/p&gt;
  &lt;ul id=&quot;j4Rt&quot;&gt;
    &lt;li id=&quot;A0bB&quot;&gt;запустить анализ страницы&lt;/li&gt;
    &lt;li id=&quot;FltH&quot;&gt;получить отчёт по:&lt;/li&gt;
    &lt;ul id=&quot;Pe7u&quot;&gt;
      &lt;li id=&quot;F6TI&quot;&gt;производительности&lt;/li&gt;
      &lt;li id=&quot;4NHV&quot;&gt;доступности (accessibility)&lt;/li&gt;
      &lt;li id=&quot;47xE&quot;&gt;SEO&lt;/li&gt;
      &lt;li id=&quot;lXBm&quot;&gt;best practices&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;l3ch&quot;&gt;После запуска анализа DevTools покажет:&lt;/p&gt;
  &lt;ul id=&quot;GxHr&quot;&gt;
    &lt;li id=&quot;R7xX&quot;&gt;какие проблемы есть&lt;/li&gt;
    &lt;li id=&quot;jghZ&quot;&gt;что можно улучшить&lt;/li&gt;
    &lt;li id=&quot;DKsN&quot;&gt;где не используется кэширование, gzip, минификация и т.д.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;5RLa&quot;&gt;Для тестировщика-джуна это &lt;strong&gt;не must-have&lt;/strong&gt;, но иногда прикольно показать:&lt;/p&gt;
  &lt;blockquote id=&quot;5bAO&quot;&gt;«Я проверил через Lighthouse, у нас низкий рейтинг по performance».&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;7BsD&quot;&gt;📱 Как включить мобильную версию сайта?&lt;/h2&gt;
  &lt;figure id=&quot;AS4o&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/6f/7e/6f7e8d5c-36ac-4373-8d0d-96ac0ee45c5a.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8Mqs&quot;&gt;В DevTools есть режим эмуляции устройства.&lt;/p&gt;
  &lt;ol id=&quot;99A8&quot;&gt;
    &lt;li id=&quot;fJIL&quot;&gt;Открой DevTools&lt;/li&gt;
    &lt;li id=&quot;Mf7c&quot;&gt;В панели сверху нажми на кнопку &lt;strong&gt;Toggle device toolbar&lt;/strong&gt;&lt;br /&gt;(иконка смартфона/планшета, обычно рядом с Select Element)&lt;/li&gt;
    &lt;li id=&quot;2pLw&quot;&gt;Выбери устройство (iPhone, Pixel и т.п.) или задай размеры вручную&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;nV6Z&quot;&gt;В этом режиме можно:&lt;/p&gt;
  &lt;ul id=&quot;Uc5F&quot;&gt;
    &lt;li id=&quot;AUjc&quot;&gt;проверить &lt;strong&gt;адаптивность&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;vd6W&quot;&gt;увидеть, как сайт выглядит на маленьком экране&lt;/li&gt;
    &lt;li id=&quot;YUxe&quot;&gt;тестировать мобильную вёрстку &lt;strong&gt;без настоящего телефона&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;sCJZ&quot;&gt;❓ Какую вкладку чаще всего держим открытой при функциональном тестировании?&lt;/h2&gt;
  &lt;p id=&quot;5TI6&quot;&gt;На практике тестировщик чаще всего держит открытыми:&lt;/p&gt;
  &lt;ul id=&quot;RLNU&quot;&gt;
    &lt;li id=&quot;fFBH&quot;&gt;&lt;strong&gt;Network&lt;/strong&gt; — чтобы смотреть запросы, ошибки, статусы&lt;/li&gt;
    &lt;li id=&quot;RH3a&quot;&gt;&lt;strong&gt;Console&lt;/strong&gt; — чтобы видеть JavaScript-ошибки&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Jwqi&quot;&gt;Если нужно выбрать прям &lt;strong&gt;одну&lt;/strong&gt;, то чаще полезнее &lt;strong&gt;Network&lt;/strong&gt;,&lt;br /&gt;потому что там:&lt;/p&gt;
  &lt;ul id=&quot;H2gO&quot;&gt;
    &lt;li id=&quot;c2GS&quot;&gt;видно все запросы&lt;/li&gt;
    &lt;li id=&quot;qhcK&quot;&gt;видно, где именно всё сломалось (сервер / фронт)&lt;/li&gt;
    &lt;li id=&quot;tbgJ&quot;&gt;видно статусы и ошибки&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Zv6u&quot;&gt;Но идеальный вариант: &lt;strong&gt;Network + Console&lt;/strong&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;NTEw&quot;&gt;🧪 Тренажёр для DevTools&lt;/h2&gt;
  &lt;blockquote id=&quot;pScF&quot;&gt;У тебя в плане указан &lt;strong&gt;тренажёр по DevTools&lt;/strong&gt;.&lt;br /&gt;Рекомендация: проходить упражнения уже после того, как:ты покликал DevTools руками,почитал эту теорию,попробовал сам:переключить мобильный режим,посмотреть запрос в Network,найти куки в Application,включить Slow 3G.&lt;/blockquote&gt;
  &lt;p id=&quot;NwpE&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;CQdJ&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;1GXx&quot;&gt;Дополнительно посмотри тут: &lt;/p&gt;
  &lt;p id=&quot;zeev&quot;&gt;&lt;a href=&quot;https://youtu.be/4iIryVM77HM?si=ZKl_ZDMjjE3-Etlv&quot; target=&quot;_blank&quot;&gt;https://youtu.be/4iIryVM77HM?si=ZKl_ZDMjjE3-Etlv&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;hx4V&quot;&gt;&lt;br /&gt;а почитай здесь: &lt;/p&gt;
  &lt;p id=&quot;1m6k&quot;&gt;&lt;a href=&quot;https://habr.com/ru/companies/fuse8/articles/799601/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/companies/fuse8/articles/799601/&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:dH9WloIStDS</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/dH9WloIStDS?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Тестовая документация</title><published>2025-10-20T07:38:52.041Z</published><updated>2025-11-26T06:53:58.449Z</updated><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/bb3/78e/46d/bb378e46d56dff73d18923990b93955b.png&quot;&gt;Краткое описание https://testengineer.ru/chto-takoe-testovaya-dokumentaciya-i-zachem-ona-nuzhna/ основных видов тестовой документации</summary><content type="html">
  &lt;figure id=&quot;fyxp&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/2f/64/2f643258-511e-47f8-bf3b-f128134092dd.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;3RYe&quot;&gt;🧾 Зачем вообще нужна тестовая документация&lt;/h2&gt;
  &lt;p id=&quot;EEDj&quot;&gt;В работе тестировщика &lt;strong&gt;≈ 25% времени&lt;/strong&gt; уходит не на «тыкание» в интерфейсе, а на:&lt;/p&gt;
  &lt;ul id=&quot;zqwJ&quot;&gt;
    &lt;li id=&quot;APYi&quot;&gt;составление &lt;strong&gt;чек-листов&lt;/strong&gt; 📝&lt;/li&gt;
    &lt;li id=&quot;0F0x&quot;&gt;написание &lt;strong&gt;тест-кейсов&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;B509&quot;&gt;оформление &lt;strong&gt;баг-репортов&lt;/strong&gt; 🐞&lt;/li&gt;
    &lt;li id=&quot;816I&quot;&gt;участие в &lt;strong&gt;тест-планах&lt;/strong&gt; и других документах&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;KtGY&quot;&gt;Это полезно:&lt;/p&gt;
  &lt;ul id=&quot;Gbrb&quot;&gt;
    &lt;li id=&quot;6vFl&quot;&gt;на собесах (очень любят спрашивать),&lt;/li&gt;
    &lt;li id=&quot;T5DR&quot;&gt;в реальной работе (без документации команда быстро утонет в хаосе).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;cZna&quot;&gt;1. Чек-лист ✅&lt;/h1&gt;
  &lt;h3 id=&quot;tEuC&quot;&gt;💡 Определение&lt;/h3&gt;
  &lt;p id=&quot;W19r&quot;&gt;&lt;strong&gt;Чек-лист&lt;/strong&gt; — это упорядоченный список пунктов (проверок), которые нужно выполнить во время тестирования.&lt;/p&gt;
  &lt;p id=&quot;IcE9&quot;&gt;Он отвечает на вопрос:&lt;/p&gt;
  &lt;blockquote id=&quot;3Vv1&quot;&gt;«Что нужно проверить, чтобы ничего не забыть?»&lt;/blockquote&gt;
  &lt;p id=&quot;YbqN&quot;&gt;Это &lt;em&gt;не&lt;/em&gt; пошаговая инструкция, а &lt;strong&gt;список того, что должно быть проверено&lt;/strong&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;L6l6&quot;&gt;🎯 Зачем нужен чек-лист&lt;/h3&gt;
  &lt;ul id=&quot;i6Ek&quot;&gt;
    &lt;li id=&quot;jOqI&quot;&gt;помогает &lt;strong&gt;ничего не забыть&lt;/strong&gt;;&lt;/li&gt;
    &lt;li id=&quot;Lm0v&quot;&gt;снижает риск &lt;strong&gt;пропустить важный баг&lt;/strong&gt;;&lt;/li&gt;
    &lt;li id=&quot;YFSE&quot;&gt;позволяет быстро пробежаться по основным функциям;&lt;/li&gt;
    &lt;li id=&quot;M6P6&quot;&gt;хорош как &lt;strong&gt;план тестирования&lt;/strong&gt; на задачу/фичу.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;WlSy&quot;&gt;✏️ Пример чек-листа для формы регистрации&lt;/h3&gt;
  &lt;ul id=&quot;4oie&quot;&gt;
    &lt;li id=&quot;Mhbb&quot;&gt;Поля «Имя», «Email», «Пароль» — обязательные&lt;/li&gt;
    &lt;li id=&quot;ci7K&quot;&gt;Неверный email обрабатывается (показывается ошибка)&lt;/li&gt;
    &lt;li id=&quot;iI48&quot;&gt;Проверка минимальной и максимальной длины пароля&lt;/li&gt;
    &lt;li id=&quot;Qdqh&quot;&gt;Проверка поля «Подтверждение пароля»&lt;/li&gt;
    &lt;li id=&quot;XnXe&quot;&gt;Кнопка «Зарегистрироваться» активна с валидными данными&lt;/li&gt;
    &lt;li id=&quot;BIb2&quot;&gt;Ошибки при незаполненных полях отображаются&lt;/li&gt;
    &lt;li id=&quot;HZGz&quot;&gt;Успешная регистрация с валидными данными&lt;/li&gt;
    &lt;li id=&quot;8c0S&quot;&gt;Отправляется подтверждающее письмо на email&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;Jqqh&quot;&gt;👀 Пример чек-листа из реального проекта (чуть упрощённо)&lt;/h3&gt;
  &lt;p id=&quot;VQ3K&quot;&gt;&lt;strong&gt;Отправленные SMS:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;Phr9&quot;&gt;
    &lt;li id=&quot;80ES&quot;&gt;На вкладке «Отправленные SMS» вообще есть такая вкладка&lt;/li&gt;
    &lt;li id=&quot;buwf&quot;&gt;Если есть отправленные SMS — они отображаются&lt;/li&gt;
    &lt;li id=&quot;UHQX&quot;&gt;В блоке «Количество SMS» показывается количество, с разбивкой по статусам&lt;/li&gt;
    &lt;li id=&quot;3jYM&quot;&gt;В блоке «Список отправленных SMS» есть детализация (кому, когда, статус и т.п.)&lt;/li&gt;
    &lt;li id=&quot;qvTB&quot;&gt;Поиск работает корректно&lt;/li&gt;
    &lt;li id=&quot;LjNJ&quot;&gt;В поле поиска можно вставлять текст&lt;/li&gt;
    &lt;li id=&quot;Ak0g&quot;&gt;Сортировка по дате работает, граничные значения учитываются&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;iNyW&quot;&gt;&lt;strong&gt;Пользователи — Лимиты SMS:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;4L4T&quot;&gt;
    &lt;li id=&quot;d1b2&quot;&gt;Отображаются номера, которые уперлись в лимит&lt;/li&gt;
    &lt;li id=&quot;26ad&quot;&gt;Для каждой записи видны: номер телефона, сервис, количество попыток, дата снятия ограничения, состояние «сброс»&lt;/li&gt;
    &lt;li id=&quot;7SpO&quot;&gt;Кнопка «Сбросить лимит» работает корректно&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;UHJa&quot;&gt;🧪 Практика (твоё упражнение)&lt;/h3&gt;
  &lt;blockquote id=&quot;nU0m&quot;&gt;&lt;strong&gt;Задание:&lt;/strong&gt;&lt;br /&gt;Выбери любой предмет из своей комнаты (например: кружка, стул, телефон, лампа) и составь &lt;strong&gt;чек-лист из 7 проверок&lt;/strong&gt; для этого предмета.&lt;br /&gt;Можно использовать:функциональные проверки (что он делает),нефункциональные (удобно ли, красиво ли, устойчиво ли и т.д.).&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;jVFU&quot;&gt;2. Тест-кейс 🧩&lt;/h1&gt;
  &lt;h3 id=&quot;91aq&quot;&gt;💡 Простое определение&lt;/h3&gt;
  &lt;p id=&quot;klU3&quot;&gt;&lt;strong&gt;Тест-кейс&lt;/strong&gt; — это &lt;strong&gt;подробный сценарий проверки&lt;/strong&gt; какого-то одного конкретного кусочка функционала.&lt;/p&gt;
  &lt;p id=&quot;dZED&quot;&gt;Он отвечает на вопросы:&lt;/p&gt;
  &lt;ul id=&quot;kzBq&quot;&gt;
    &lt;li id=&quot;J57M&quot;&gt;&lt;strong&gt;что&lt;/strong&gt; проверяем,&lt;/li&gt;
    &lt;li id=&quot;XtbY&quot;&gt;&lt;strong&gt;в каких условиях&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;nXjz&quot;&gt;&lt;strong&gt;какими шагами&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;a9qg&quot;&gt;&lt;strong&gt;что должно получиться&lt;/strong&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;DqG5&quot;&gt;Это уже &lt;strong&gt;не просто список пунктов&lt;/strong&gt;, а &lt;strong&gt;пошаговая инструкция&lt;/strong&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;YQbs&quot;&gt;💡 Формальное определение (чуть серьёзнее)&lt;/h3&gt;
  &lt;blockquote id=&quot;eIOk&quot;&gt;Тест-кейс — набор:входных данных,предусловий,шагов выполнения,ожидаемых результатов и постусловий,&lt;br /&gt;созданный для проверки определённого требования или сценария.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;dzY0&quot;&gt;🧱 Обязательные атрибуты тест-кейса&lt;/h3&gt;
  &lt;p id=&quot;Qn0p&quot;&gt;То, без чего нормальный тест-кейс жить не может:&lt;/p&gt;
  &lt;ol id=&quot;NQwO&quot;&gt;
    &lt;li id=&quot;zK2k&quot;&gt;🆔 &lt;strong&gt;Уникальный идентификатор&lt;/strong&gt;&lt;br /&gt;Номер тест-кейса (например, &lt;code&gt;TC-REG-001&lt;/code&gt;).&lt;/li&gt;
    &lt;li id=&quot;8A61&quot;&gt;🏷 &lt;strong&gt;Название&lt;/strong&gt;&lt;br /&gt;Кратко и понятно:&lt;br /&gt;«Регистрация с валидными данными»&lt;/li&gt;
    &lt;li id=&quot;4hN7&quot;&gt;⚙️ &lt;strong&gt;Предусловия (Preconditions)&lt;/strong&gt;&lt;br /&gt;Что должно быть выполнено &lt;strong&gt;до начала&lt;/strong&gt; шагов, например:&lt;/li&gt;
    &lt;ul id=&quot;VlSi&quot;&gt;
      &lt;li id=&quot;9O9A&quot;&gt;«Пользователь не зарегистрирован»&lt;/li&gt;
      &lt;li id=&quot;LHih&quot;&gt;«Открыта главная страница сайта»&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;L9Bu&quot;&gt;👣 &lt;strong&gt;Шаги&lt;/strong&gt;&lt;br /&gt;Последовательность действий. Каждый шаг — это &lt;strong&gt;действие&lt;/strong&gt;, а не наблюдение:&lt;/li&gt;
    &lt;ul id=&quot;0SrR&quot;&gt;
      &lt;li id=&quot;uRqi&quot;&gt;Открыть страницу регистрации&lt;/li&gt;
      &lt;li id=&quot;y95J&quot;&gt;Ввести в поле «Email» …&lt;/li&gt;
      &lt;li id=&quot;yqV9&quot;&gt;Нажать кнопку «Зарегистрироваться»&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;1c6m&quot;&gt;🎯 &lt;strong&gt;Ожидаемый результат&lt;/strong&gt;&lt;br /&gt;Что именно мы должны увидеть после выполнения шагов:&lt;/li&gt;
    &lt;ul id=&quot;Kzjd&quot;&gt;
      &lt;li id=&quot;Of5S&quot;&gt;Пользователь успешно зарегистрирован&lt;/li&gt;
      &lt;li id=&quot;ocXa&quot;&gt;Появилось сообщение «Проверьте почту»&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;BBX6&quot;&gt;Дополнительно (желательно, но не строго обязательно):&lt;/p&gt;
  &lt;ul id=&quot;w4WO&quot;&gt;
    &lt;li id=&quot;rmgU&quot;&gt;📜 История изменений (кто, когда менял тест-кейс)&lt;/li&gt;
    &lt;li id=&quot;yWMy&quot;&gt;📌 Ссылка на требование / макет / задачу&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;FtA2&quot;&gt;✅ Результаты выполнения тест-кейса&lt;/h3&gt;
  &lt;p id=&quot;xU7U&quot;&gt;Когда мы &lt;em&gt;выполнили&lt;/em&gt; тест-кейс, он может дать один из трёх статусов:&lt;/p&gt;
  &lt;ol id=&quot;j8sc&quot;&gt;
    &lt;li id=&quot;n0rV&quot;&gt;&lt;strong&gt;Положительный (Passed)&lt;/strong&gt;&lt;br /&gt;Фактический результат = ожидаемому. Всё хорошо.&lt;/li&gt;
    &lt;li id=&quot;2uQg&quot;&gt;&lt;strong&gt;Отрицательный (Failed)&lt;/strong&gt;&lt;br /&gt;Фактический ≠ ожидаемому. Нашли баг.&lt;/li&gt;
    &lt;li id=&quot;gZ0U&quot;&gt;&lt;strong&gt;Блокирован (Blocked)&lt;/strong&gt;&lt;br /&gt;Невозможно продолжать, потому что что-то сломалось раньше (тоже баг, но блокирующий тест).&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;BCXe&quot;&gt;❌ Чего не должно быть в тест-кейсе&lt;/h3&gt;
  &lt;ol id=&quot;MexL&quot;&gt;
    &lt;li id=&quot;xsA8&quot;&gt;&lt;strong&gt;Зависимостей от других тест-кейсов&lt;/strong&gt;&lt;br /&gt;Тест должен быть максимально самодостаточным.&lt;/li&gt;
    &lt;li id=&quot;Stdc&quot;&gt;&lt;strong&gt;Нечётких формулировок&lt;/strong&gt;&lt;br /&gt;Типа: «проверить, что всё нормально».&lt;br /&gt;Надо конкретно: «отображается сообщение &amp;quot;Успешно сохранено&amp;quot;».&lt;/li&gt;
    &lt;li id=&quot;LmUU&quot;&gt;&lt;strong&gt;Отсутствия важной информации&lt;/strong&gt;&lt;br /&gt;Нельзя написать «проверить логин» и не указать логин и пароль (или ссылку на источник этих данных).&lt;/li&gt;
    &lt;li id=&quot;3vZK&quot;&gt;&lt;strong&gt;Излишней детализации&lt;/strong&gt;&lt;br /&gt;Не нужно писать «нажать цифру 1 на клавиатуре, затем 2» — достаточно «ввести значение 12».&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;IdzV&quot;&gt;🧪 Пример тест-кейса (упрощённый)&lt;/h3&gt;
  &lt;p id=&quot;pTNu&quot;&gt;&lt;strong&gt;Название:&lt;/strong&gt; Регистрация пользователя с валидными данными&lt;br /&gt;&lt;strong&gt;Предусловия:&lt;/strong&gt; Пользователь не зарегистрирован в системе&lt;/p&gt;
  &lt;p id=&quot;Qd6a&quot;&gt;&lt;strong&gt;Шаги:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;Q0Zh&quot;&gt;
    &lt;li id=&quot;AvSk&quot;&gt;Открыть страницу регистрации&lt;/li&gt;
    &lt;li id=&quot;8AMj&quot;&gt;Ввести в поле «Имя» — &lt;code&gt;Иван Иванов&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;BB6Z&quot;&gt;Ввести в поле «Email» — &lt;code&gt;ivan.ivanov@example.com&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;gZjr&quot;&gt;Ввести в поле «Пароль» — &lt;code&gt;Password123&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;Je3t&quot;&gt;Повторить пароль в поле «Подтверждение пароля»&lt;/li&gt;
    &lt;li id=&quot;yUaR&quot;&gt;Нажать кнопку «Зарегистрироваться»&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;3ymn&quot;&gt;&lt;strong&gt;Ожидаемый результат:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;WQSn&quot;&gt;
    &lt;li id=&quot;IGvT&quot;&gt;Пользователь успешно зарегистрирован&lt;/li&gt;
    &lt;li id=&quot;VUQh&quot;&gt;Отображается сообщение «Проверьте вашу почту»&lt;/li&gt;
    &lt;li id=&quot;pwCt&quot;&gt;На email отправлено письмо с подтверждением&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;j6as&quot;&gt;🧮 Уровни детализации тест-кейсов&lt;/h3&gt;
  &lt;ul id=&quot;yWjX&quot;&gt;
    &lt;li id=&quot;d87M&quot;&gt;&lt;strong&gt;Верхнеуровневые&lt;/strong&gt; — общие, без суперподробностей«Зарегистрировать пользователя с валидными данными»&lt;/li&gt;
    &lt;li id=&quot;HV6f&quot;&gt;&lt;strong&gt;Низкоуровневые&lt;/strong&gt; — очень детальныекаждый шаг расписан, как для человека, который впервые видит систему.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;r7lT&quot;&gt;Ты сам/а будешь подбирать уровень детализации под:&lt;/p&gt;
  &lt;ul id=&quot;Ziuw&quot;&gt;
    &lt;li id=&quot;nWmg&quot;&gt;сложность функционала,&lt;/li&gt;
    &lt;li id=&quot;Qju2&quot;&gt;опыт команды,&lt;/li&gt;
    &lt;li id=&quot;bo8R&quot;&gt;требования проекта.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;ggGQ&quot;&gt;🛠 Инструменты&lt;/h3&gt;
  &lt;ul id=&quot;2e1J&quot;&gt;
    &lt;li id=&quot;TuuA&quot;&gt;Для написания тест-кейсов можно использовать:&lt;/li&gt;
    &lt;ul id=&quot;J7j1&quot;&gt;
      &lt;li id=&quot;4uZG&quot;&gt;Google-таблицы / Excel&lt;/li&gt;
      &lt;li id=&quot;7imq&quot;&gt;Документы&lt;/li&gt;
      &lt;li id=&quot;uzb4&quot;&gt;или &lt;strong&gt;TMS&lt;/strong&gt; (Test Management System), например &lt;strong&gt;Qase&lt;/strong&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;Nd7X&quot;&gt;🧪 Практика (твоё упражнение)&lt;/h3&gt;
  &lt;blockquote id=&quot;gh6u&quot;&gt;&lt;strong&gt;Задание:&lt;/strong&gt;&lt;br /&gt;Составь &lt;strong&gt;тест-кейс&lt;/strong&gt; на проверку любой функциональности интернет-магазина:авторизация,добавление товара в корзину,оформление заказа,поиск товара и т.д.Оформи:в таблице,в документе,или в TMS (например, Qase).Потом приложи файл или скрин.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;fb5O&quot;&gt;&lt;/h1&gt;
  &lt;figure id=&quot;AVaY&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/40/23/4023d33c-4c36-4c37-b891-420c8d23a1a7.jpeg&quot; width=&quot;1024&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;lGmK&quot;&gt;3. Тест-план 📋&lt;/h2&gt;
  &lt;p id=&quot;u6Rz&quot;&gt;&lt;strong&gt;Тест-план&lt;/strong&gt; — это уже не один сценарий, а &lt;strong&gt;стратегический документ&lt;/strong&gt;, который описывает:&lt;/p&gt;
  &lt;ul id=&quot;ZKrt&quot;&gt;
    &lt;li id=&quot;vzO5&quot;&gt;что именно мы будем тестировать (объект тестирования),&lt;/li&gt;
    &lt;li id=&quot;GVPW&quot;&gt;стратегию и подходы (как будем тестировать),&lt;/li&gt;
    &lt;li id=&quot;xtV0&quot;&gt;график тестирования,&lt;/li&gt;
    &lt;li id=&quot;RZ1S&quot;&gt;критерии «начать» и «закончить» тестирование,&lt;/li&gt;
    &lt;li id=&quot;tz4o&quot;&gt;какие ресурсы и окружение нужны,&lt;/li&gt;
    &lt;li id=&quot;JaeE&quot;&gt;какие есть риски и что будем делать, если они проявятся.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;FM9R&quot;&gt;Обычно тест-план делают &lt;strong&gt;лиды / сеньоры&lt;/strong&gt;, но джуну полезно понимать, что это такое.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;FTrk&quot;&gt;4. Баг-репорт 🐞&lt;/h1&gt;
  &lt;h3 id=&quot;dDCA&quot;&gt;💡 Определение&lt;/h3&gt;
  &lt;p id=&quot;UPEn&quot;&gt;&lt;strong&gt;Баг-репорт&lt;/strong&gt; — это официальное описание найденной ошибки, которое помогает:&lt;/p&gt;
  &lt;ul id=&quot;ZK7C&quot;&gt;
    &lt;li id=&quot;OoTu&quot;&gt;разработчику понять, &lt;strong&gt;что именно сломалось&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;WthK&quot;&gt;как &lt;strong&gt;воспроизвести&lt;/strong&gt; проблему,&lt;/li&gt;
    &lt;li id=&quot;FgFB&quot;&gt;насколько она &lt;strong&gt;серьёзна&lt;/strong&gt; и &lt;strong&gt;важна&lt;/strong&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;iAAB&quot;&gt;Хороший баг-репорт отвечает на два главных пункта:&lt;/p&gt;
  &lt;ol id=&quot;GM4P&quot;&gt;
    &lt;li id=&quot;IbHJ&quot;&gt;Можно ли &lt;strong&gt;воспроизвести&lt;/strong&gt; проблему?&lt;/li&gt;
    &lt;li id=&quot;zBBH&quot;&gt;Понятно ли, &lt;strong&gt;в чём суть&lt;/strong&gt; и насколько это важно?&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;cqXV&quot;&gt;🧱 Обязательные поля баг-репорта&lt;/h3&gt;
  &lt;p id=&quot;Uk6X&quot;&gt;Общая структура (конкретные поля зависят от баг-трекера, но суть такая):&lt;/p&gt;
  &lt;ol id=&quot;SMDZ&quot;&gt;
    &lt;li id=&quot;hBwf&quot;&gt;🏷 &lt;strong&gt;Заголовок (Title)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;u31l&quot;&gt;📋 &lt;strong&gt;Описание / Шаги воспроизведения (Steps to Reproduce)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;juX3&quot;&gt;🎯 &lt;strong&gt;Фактический результат (Actual result)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;K8Gi&quot;&gt;✅ &lt;strong&gt;Ожидаемый результат (Expected result)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;Kd6Y&quot;&gt;💣 &lt;strong&gt;Severity (серьёзность)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;ZnQn&quot;&gt;🚦 &lt;strong&gt;Priority (приоритет)&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;MRzg&quot;&gt;💻 &lt;strong&gt;Environment (окружение)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;3gH9&quot;&gt;
      &lt;li id=&quot;w4OH&quot;&gt;ОС, браузер, версия приложения и т.д.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;lgpH&quot;&gt;📎 &lt;strong&gt;Вложения (Attachments)&lt;/strong&gt;&lt;/li&gt;
    &lt;ul id=&quot;HMts&quot;&gt;
      &lt;li id=&quot;Rxuw&quot;&gt;скриншоты, логи, тестовые данные и т.п.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;faUe&quot;&gt;🔍 Название баг-репорта: «Что? Где? Когда?»&lt;/h3&gt;
  &lt;p id=&quot;0s5b&quot;&gt;Хорошее название должно отвечать на 3 вопроса:&lt;/p&gt;
  &lt;ol id=&quot;dNIi&quot;&gt;
    &lt;li id=&quot;utQ9&quot;&gt;&lt;strong&gt;Что?&lt;/strong&gt; — что сломалось и как именно?«Картинка с котиком уезжает за пределы экрана»&lt;/li&gt;
    &lt;li id=&quot;efU1&quot;&gt;&lt;strong&gt;Где?&lt;/strong&gt; — где именно проблема? (страница, модуль, компонент)«…на главной странице»&lt;/li&gt;
    &lt;li id=&quot;SNAL&quot;&gt;&lt;strong&gt;Когда?&lt;/strong&gt; — при каких условиях/действиях это происходит?«…при ширине окна браузера менее 500px»&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;BnJz&quot;&gt;Итоговое название:&lt;/p&gt;
  &lt;blockquote id=&quot;cUFX&quot;&gt;«Картинка с котиком на главной странице уезжает за границу экрана при ширине окна &amp;lt; 500px»&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;dSe5&quot;&gt;🎚 Серьёзность багов (Severity)&lt;/h3&gt;
  &lt;p id=&quot;c2KO&quot;&gt;&lt;strong&gt;Severity&lt;/strong&gt; — это &lt;strong&gt;насколько сильно баг ломает систему&lt;/strong&gt; с технической точки зрения.&lt;/p&gt;
  &lt;p id=&quot;tHAJ&quot;&gt;Пример уровней:&lt;/p&gt;
  &lt;ul id=&quot;rGGL&quot;&gt;
    &lt;li id=&quot;wxgX&quot;&gt;🟥 &lt;strong&gt;Critical / Blocker&lt;/strong&gt; — ничего не работает: система падает, невозможно зайти, оформить заказ и т.д.&lt;/li&gt;
    &lt;li id=&quot;COke&quot;&gt;🔴 &lt;strong&gt;Major / High&lt;/strong&gt; — важная функциональность ломается, но система не падает полностью.&lt;/li&gt;
    &lt;li id=&quot;pCer&quot;&gt;🟠 &lt;strong&gt;Medium&lt;/strong&gt; — заметно, мешает, но можно жить.&lt;/li&gt;
    &lt;li id=&quot;Xsd1&quot;&gt;🟢 &lt;strong&gt;Minor / Low&lt;/strong&gt; — мелочь: опечатка, пиксель влево, цвет не тот.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;b8Or&quot;&gt;🚦 Приоритет багов (Priority)&lt;/h3&gt;
  &lt;p id=&quot;qqT3&quot;&gt;&lt;strong&gt;Priority&lt;/strong&gt; — это &lt;strong&gt;насколько срочно&lt;/strong&gt; нужно чинить баг &lt;em&gt;для бизнеса&lt;/em&gt;.&lt;/p&gt;
  &lt;ul id=&quot;xES4&quot;&gt;
    &lt;li id=&quot;S1g2&quot;&gt;High — чинить сразу&lt;/li&gt;
    &lt;li id=&quot;Mb9H&quot;&gt;Medium — чинить в ближайших релизах&lt;/li&gt;
    &lt;li id=&quot;P9Ev&quot;&gt;Low — можно отложить&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;PQLx&quot;&gt;Иногда баг &lt;strong&gt;технически не страшный&lt;/strong&gt;, но &lt;strong&gt;очень важный для бизнеса&lt;/strong&gt; (например, опечатка в цене на главном баннере).&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;Di35&quot;&gt;🔁 Примеры комбинаций: Severity vs Priority&lt;/h3&gt;
  &lt;h4 id=&quot;e1MR&quot;&gt;🔼 Высокий приоритет, низкая серьёзность&lt;/h4&gt;
  &lt;p id=&quot;gGQI&quot;&gt;Например:&lt;/p&gt;
  &lt;ul id=&quot;xoTy&quot;&gt;
    &lt;li id=&quot;69Zw&quot;&gt;Важный лендинг, на главной кнопке вместо «Купить» написано «Купипь».&lt;/li&gt;
    &lt;li id=&quot;Ricl&quot;&gt;Функционально всё работает, &lt;strong&gt;система не ломается&lt;/strong&gt;, но&lt;/li&gt;
    &lt;ul id=&quot;WTdZ&quot;&gt;
      &lt;li id=&quot;Q6rd&quot;&gt;это видят все пользователи,&lt;/li&gt;
      &lt;li id=&quot;4xrR&quot;&gt;репутация страдает,&lt;/li&gt;
      &lt;li id=&quot;62TS&quot;&gt;руководство в ярости.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;5OUY&quot;&gt;&lt;strong&gt;Severity&lt;/strong&gt; — Low (опечатка)&lt;br /&gt;&lt;strong&gt;Priority&lt;/strong&gt; — High (чинить быстро).&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h4 id=&quot;NvpX&quot;&gt;🔼 Высокая серьёзность, низкий приоритет&lt;/h4&gt;
  &lt;p id=&quot;1paL&quot;&gt;Например:&lt;/p&gt;
  &lt;ul id=&quot;JJMT&quot;&gt;
    &lt;li id=&quot;iyad&quot;&gt;В старом разделе отчётов, которым никто не пользуется,&lt;/li&gt;
    &lt;li id=&quot;IWOR&quot;&gt;при очень специфическом наборе фильтров&lt;/li&gt;
    &lt;li id=&quot;Ijcf&quot;&gt;система падает с ошибкой.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;JS6U&quot;&gt;Технически: &lt;strong&gt;серьёзно&lt;/strong&gt;, падение.&lt;br /&gt;Но бизнес говорит: «Этот отчёт будет удалён через месяц, никто им не пользуется».&lt;/p&gt;
  &lt;p id=&quot;IgkL&quot;&gt;&lt;strong&gt;Severity&lt;/strong&gt; — High / Critical&lt;br /&gt;&lt;strong&gt;Priority&lt;/strong&gt; — Low&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;SuaL&quot;&gt;🧪 Практика (твоё упражнение)&lt;/h3&gt;
  &lt;blockquote id=&quot;Vp6K&quot;&gt;&lt;strong&gt;Задание:&lt;/strong&gt;&lt;br /&gt;Найди &lt;strong&gt;3 бага на любом сайте&lt;/strong&gt; (можно учебный проект, демо-сайт, даже формочки простые) и:Оформи 3 баг-репортаВ любом виде: таблица, текстовый документОбязательно укажи:заголовок (с «что/где/когда»),шаги,ожидаемый результат,фактический результат,severity и priority.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;jDzx&quot;&gt;5. Скриншоты и Lightshot 📸&lt;/h1&gt;
  &lt;p id=&quot;8WRg&quot;&gt;В баг-репортах &lt;strong&gt;очень полезно&lt;/strong&gt; прикладывать:&lt;/p&gt;
  &lt;ul id=&quot;A2GB&quot;&gt;
    &lt;li id=&quot;73Va&quot;&gt;скриншоты,&lt;/li&gt;
    &lt;li id=&quot;xWKs&quot;&gt;иногда видео.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;coW4&quot;&gt;Для работы со скриншотами удобно:&lt;/p&gt;
  &lt;p id=&quot;PA9p&quot;&gt;👉 &lt;strong&gt;Lightshot&lt;/strong&gt; — &lt;code&gt;https://app.prntscr.com/ru/index.html&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;qM6h&quot;&gt;Ты можешь:&lt;/p&gt;
  &lt;ul id=&quot;VUyF&quot;&gt;
    &lt;li id=&quot;DQCC&quot;&gt;вставлять скрин прямо в баг-репорт,&lt;/li&gt;
    &lt;li id=&quot;iPVZ&quot;&gt;или заливать в облако и прикреплять ссылку.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;eP1H&quot;&gt;Если баг &lt;strong&gt;визуальный&lt;/strong&gt; (верстка, отступы, вылезла картинка) — скриншот почти обязателен.&lt;br /&gt;Хорошо, если на скрине ты &lt;strong&gt;подсветишь место ошибки&lt;/strong&gt; стрелочкой или рамкой.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;biCC&quot;&gt;6. Частые ошибки в тестовой документации 🚫&lt;/h1&gt;
  &lt;p id=&quot;SrGl&quot;&gt;Особенно при написании &lt;strong&gt;тест-кейсов и баг-репортов&lt;/strong&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;Vk2F&quot;&gt;1️⃣ Ошмётки ожидаемого результата в шагах&lt;/h3&gt;
  &lt;p id=&quot;HLVJ&quot;&gt;❌ Плохо:&lt;/p&gt;
  &lt;blockquote id=&quot;Ofws&quot;&gt;Шаг 2: Нажать на кнопку &amp;quot;HERE&amp;quot; в строчке для перехода на следующую страницу&lt;/blockquote&gt;
  &lt;p id=&quot;64Ov&quot;&gt;Здесь в шаг шагами уже залезла часть «что произойдёт».&lt;/p&gt;
  &lt;p id=&quot;WCip&quot;&gt;✅ Лучше разделить:&lt;/p&gt;
  &lt;p id=&quot;4cW6&quot;&gt;&lt;strong&gt;Шаг 2:&lt;/strong&gt; Нажать на кнопку «HERE»&lt;br /&gt;&lt;strong&gt;Ожидаемый результат:&lt;/strong&gt; Переход на страницу регистрации&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;FEV8&quot;&gt;2️⃣ Ошмётки шагов в ожидаемом результате&lt;/h3&gt;
  &lt;p id=&quot;HdOf&quot;&gt;❌ Плохо:&lt;/p&gt;
  &lt;blockquote id=&quot;57NX&quot;&gt;Ожидаемый результат: При нажатии на кнопку Sign In происходит переход на страницу авторизации&lt;/blockquote&gt;
  &lt;p id=&quot;mV5k&quot;&gt;Мы уже написали «нажать кнопку» в шагах.&lt;/p&gt;
  &lt;p id=&quot;0lav&quot;&gt;✅ Лучше:&lt;/p&gt;
  &lt;p id=&quot;cxol&quot;&gt;&lt;strong&gt;Шаг 3:&lt;/strong&gt; Нажать на кнопку Sign In&lt;br /&gt;&lt;strong&gt;Ожидаемый результат:&lt;/strong&gt; Происходит переход на страницу авторизации&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;BPM9&quot;&gt;3️⃣ Несколько багов в одном баг-репорте&lt;/h3&gt;
  &lt;p id=&quot;OMOD&quot;&gt;❌ Плохо:&lt;/p&gt;
  &lt;blockquote id=&quot;sPA7&quot;&gt;«Зелёная кнопка на главной странице имеет текст &amp;quot;No&amp;quot; и её нажатие не приводит к переходу на страницу Х»&lt;/blockquote&gt;
  &lt;p id=&quot;UvgZ&quot;&gt;Тут &lt;strong&gt;два бага&lt;/strong&gt;:&lt;/p&gt;
  &lt;ol id=&quot;H3ax&quot;&gt;
    &lt;li id=&quot;g1Km&quot;&gt;Текст кнопки неправильный&lt;/li&gt;
    &lt;li id=&quot;Dicx&quot;&gt;Переход не работает&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;i8o9&quot;&gt;✅ Лучше сделать &lt;strong&gt;два отдельных баг-репорта&lt;/strong&gt;:&lt;/p&gt;
  &lt;ol id=&quot;9ATc&quot;&gt;
    &lt;li id=&quot;dH8u&quot;&gt;«Текст &amp;quot;No&amp;quot; на зелёной кнопке на главной странице»&lt;/li&gt;
    &lt;li id=&quot;0f7a&quot;&gt;«При нажатии зелёной кнопки на главной странице не происходит переход на страницу Х»&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;yxgi&quot;&gt;Почему важно разделять:&lt;/p&gt;
  &lt;ul id=&quot;Sf7r&quot;&gt;
    &lt;li id=&quot;exym&quot;&gt;один пофиксят, второй забудут;&lt;/li&gt;
    &lt;li id=&quot;nyaN&quot;&gt;у багов может быть разный приоритет;&lt;/li&gt;
    &lt;li id=&quot;zOhA&quot;&gt;так ты показываешь больше собственной работы 😏&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;8hSi&quot;&gt;7. Чек-лист самопроверки для тебя 🧠&lt;/h1&gt;
  &lt;p id=&quot;K2lN&quot;&gt;Когда напишешь:&lt;/p&gt;
  &lt;ul id=&quot;1IVx&quot;&gt;
    &lt;li id=&quot;3bpW&quot;&gt;чек-лист,&lt;/li&gt;
    &lt;li id=&quot;U9da&quot;&gt;тест-кейс,&lt;/li&gt;
    &lt;li id=&quot;VScH&quot;&gt;баг-репорты —&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;4Kgw&quot;&gt;пробегись по вопросам:&lt;/p&gt;
  &lt;ul id=&quot;mlBM&quot;&gt;
    &lt;li id=&quot;r3bV&quot;&gt;Понятно ли &lt;strong&gt;не-автору&lt;/strong&gt;, что нужно делать?&lt;/li&gt;
    &lt;li id=&quot;Mapx&quot;&gt;Есть ли &lt;strong&gt;конкретные шаги&lt;/strong&gt;, а не «проверить, что всё корректно»?&lt;/li&gt;
    &lt;li id=&quot;bfCC&quot;&gt;Разделены ли:&lt;/li&gt;
    &lt;ul id=&quot;ZvCR&quot;&gt;
      &lt;li id=&quot;G9mu&quot;&gt;шаги&lt;/li&gt;
      &lt;li id=&quot;ckNJ&quot;&gt;ожидаемый результат&lt;/li&gt;
      &lt;li id=&quot;Gqid&quot;&gt;фактический результат&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;niZ7&quot;&gt;Нет ли &lt;strong&gt;двух багов в одном репорте&lt;/strong&gt;?&lt;/li&gt;
    &lt;li id=&quot;xxSm&quot;&gt;Заголовок бага отвечает на «Что? Где? Когда?»?&lt;/li&gt;
    &lt;li id=&quot;Ulcw&quot;&gt;Severity и Priority логичны?&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;x0L5&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;kgd5&quot;&gt;Дополнительно посмотри тут:&lt;/p&gt;
  &lt;p id=&quot;md5s&quot;&gt;&lt;a href=&quot;https://youtu.be/OHJ3TzuLSC0?si=pxFBcjbP1YeRFL_9&quot; target=&quot;_blank&quot;&gt;https://youtu.be/OHJ3TzuLSC0?si=pxFBcjbP1YeRFL_9&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>maya.work905:KewyE9J8NKX</id><link rel="alternate" type="text/html" href="https://teletype.in/@maya.work905/KewyE9J8NKX?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=maya.work905"></link><title>Техники тест-дизайна</title><published>2025-10-20T07:15:49.223Z</published><updated>2025-11-26T06:51:50.767Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/cc/cf/cccfa44d-7f81-49e3-b71f-069c3323c73f.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://club.directum.ru/uploads/images/primer_tekhniki_ehkvivaletnogo_razbienijapng_0918c656d20f4f25b82fed253074ded1.png&quot;&gt;https://testengineer.ru/tekhniki-test-dizajna-teoriya-i-primery/</summary><content type="html">
  &lt;h1 id=&quot;kHzP&quot;&gt;🧠 Что такое тест-дизайн (по-человечески)&lt;/h1&gt;
  &lt;figure id=&quot;qS3d&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/63/25/6325c949-031f-4902-b5c3-a8390c385335.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YZ9Q&quot;&gt;&lt;strong&gt;Тест-дизайн&lt;/strong&gt; — это этап, на котором мы решаем:&lt;/p&gt;
  &lt;ul id=&quot;obx4&quot;&gt;
    &lt;li id=&quot;xFAR&quot;&gt;&lt;em&gt;что именно будем проверять;&lt;/em&gt;&lt;/li&gt;
    &lt;li id=&quot;EJjl&quot;&gt;&lt;em&gt;какими тестами это проверим;&lt;/em&gt;&lt;/li&gt;
    &lt;li id=&quot;Dj5d&quot;&gt;&lt;em&gt;какими данными будем пользоваться.&lt;/em&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;8UIo&quot;&gt;То есть тест-дизайн — это &lt;strong&gt;мостик между ТЗ и реальными тест-кейсами&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;iWCh&quot;&gt;💡 &lt;em&gt;Без тест-дизайна&lt;/em&gt; тестировщик просто «тыкает куда попало».&lt;br /&gt;💡 &lt;em&gt;С тест-дизайном&lt;/em&gt; — работает по понятной системе и ловит больше багов меньшим количеством тестов.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;a6qI&quot;&gt;🎯 Цели тест-дизайна&lt;/h2&gt;
  &lt;p id=&quot;3R42&quot;&gt;Зачем вообще всё это нужно:&lt;/p&gt;
  &lt;ul id=&quot;EkHZ&quot;&gt;
    &lt;li id=&quot;d8Lg&quot;&gt;🐛 &lt;strong&gt;Находить самые серьёзные ошибки&lt;/strong&gt; — особенно там, где система ломается по-настоящему.&lt;/li&gt;
    &lt;li id=&quot;FG1b&quot;&gt;✂️ &lt;strong&gt;Уменьшить количество тест-кейсов&lt;/strong&gt; — не проверять 1000 вариантов, если достаточно 10 умных.&lt;/li&gt;
    &lt;li id=&quot;vt3O&quot;&gt;⏱️ &lt;strong&gt;Сократить время на тестирование&lt;/strong&gt; — тестов меньше, а пользы больше.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;pgQN&quot;&gt;🧩 Этапы тест-дизайна&lt;/h2&gt;
  &lt;p id=&quot;2otF&quot;&gt;Очень упрощённо:&lt;/p&gt;
  &lt;ol id=&quot;D65N&quot;&gt;
    &lt;li id=&quot;2vw2&quot;&gt;&lt;strong&gt;Анализ материалов&lt;/strong&gt;&lt;br /&gt;Читаем:&lt;/li&gt;
    &lt;ul id=&quot;Df2n&quot;&gt;
      &lt;li id=&quot;vjb1&quot;&gt;требования,&lt;/li&gt;
      &lt;li id=&quot;OwsN&quot;&gt;спецификации,&lt;/li&gt;
      &lt;li id=&quot;lgNu&quot;&gt;макеты,&lt;/li&gt;
      &lt;li id=&quot;FLXr&quot;&gt;схемы,&lt;/li&gt;
      &lt;li id=&quot;iQun&quot;&gt;иногда даже код.&lt;br /&gt;Задача — понять: &lt;em&gt;что должен делать продукт&lt;/em&gt;.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;liUb&quot;&gt;&lt;strong&gt;(Иногда) спецификация тест-дизайна&lt;/strong&gt;&lt;br /&gt;Это документ, где мы фиксируем:&lt;/li&gt;
    &lt;ul id=&quot;l4aN&quot;&gt;
      &lt;li id=&quot;lXiy&quot;&gt;подход к тестированию,&lt;/li&gt;
      &lt;li id=&quot;SFzK&quot;&gt;какие техники используем,&lt;/li&gt;
      &lt;li id=&quot;xmv4&quot;&gt;что считаем приоритетом.&lt;br /&gt;Это не обязательно, но полезно для командной работы.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;G3Ti&quot;&gt;&lt;strong&gt;Проектирование тест-кейсов&lt;/strong&gt;&lt;br /&gt;Используем техники тест-дизайна и превращаем их:&lt;/li&gt;
    &lt;ul id=&quot;JpXZ&quot;&gt;
      &lt;li id=&quot;qMIu&quot;&gt;в конкретные сценарии,&lt;/li&gt;
      &lt;li id=&quot;jGB9&quot;&gt;в набор тестовых данных.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;Pd0A&quot;&gt;🧰 Какие бывают техники тест-дизайна?&lt;/h1&gt;
  &lt;p id=&quot;yitD&quot;&gt;Техники — это &lt;strong&gt;инструменты&lt;/strong&gt;, которые помогают:&lt;/p&gt;
  &lt;ul id=&quot;XaTa&quot;&gt;
    &lt;li id=&quot;7KWQ&quot;&gt;определить, &lt;strong&gt;какие данные взять&lt;/strong&gt;;&lt;/li&gt;
    &lt;li id=&quot;PbAV&quot;&gt;какие &lt;strong&gt;случаи обязательно проверить&lt;/strong&gt;;&lt;/li&gt;
    &lt;li id=&quot;DCix&quot;&gt;как &lt;strong&gt;сократить количество тестов&lt;/strong&gt;, не потеряв качество.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;roIL&quot;&gt;Их делят на три большие группы:&lt;/p&gt;
  &lt;ol id=&quot;rePJ&quot;&gt;
    &lt;li id=&quot;YsnC&quot;&gt;🎱 &lt;strong&gt;Техники чёрного ящика&lt;/strong&gt;&lt;br /&gt;Смотрим только на поведение системы:&lt;br /&gt;«что на вход — что на выход».&lt;br /&gt;&lt;em&gt;Код нас не волнует.&lt;/em&gt;&lt;/li&gt;
    &lt;li id=&quot;98cf&quot;&gt;⚙️ &lt;strong&gt;Техники белого ящика&lt;/strong&gt;&lt;br /&gt;Смотрим во внутренности:&lt;br /&gt;«как устроен код, какие ветки, циклы».&lt;br /&gt;Обычно это зона разработчиков / автотестов на уровне кода.&lt;/li&gt;
    &lt;li id=&quot;uEIw&quot;&gt;🧪 &lt;strong&gt;Техники, основанные на опыте&lt;/strong&gt;&lt;br /&gt;Используем:&lt;/li&gt;
    &lt;ul id=&quot;pFhT&quot;&gt;
      &lt;li id=&quot;WOTx&quot;&gt;собственный опыт,&lt;/li&gt;
      &lt;li id=&quot;sDVD&quot;&gt;знание типичных багов,&lt;/li&gt;
      &lt;li id=&quot;3fKn&quot;&gt;историю проекта.&lt;br /&gt;Сюда относятся, например, &lt;em&gt;прогнозирование ошибок&lt;/em&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;NpZg&quot;&gt;В этой карточке мы фокусируемся на &lt;strong&gt;чёрном ящике&lt;/strong&gt;, потому что это база для ручного тестировщика.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;FgEy&quot;&gt;1️⃣ Эквивалентное разбиение (эквивалентные классы) ⚖️&lt;/h1&gt;
  &lt;h2 id=&quot;nD8A&quot;&gt;🧩 Суть техники&lt;/h2&gt;
  &lt;p id=&quot;NEpq&quot;&gt;&lt;strong&gt;Эквивалентное разбиение&lt;/strong&gt; — это когда мы &lt;strong&gt;делим все возможные входные значения на группы (классы)&lt;/strong&gt;, внутри которых значения «ведут себя одинаково» для системы.&lt;/p&gt;
  &lt;p id=&quot;IjTu&quot;&gt;👉 Идея:&lt;br /&gt;&lt;em&gt;Если одно значение из класса ведёт себя правильно/неправильно — то остальные в этом классе, скорее всего, так же.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;5W98&quot;&gt;Поэтому &lt;strong&gt;нет смысла тестировать каждое число, каждую строку&lt;/strong&gt; — достаточно выбрать по одному представителю из каждого класса.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Oloo&quot;&gt;💻 Как применять технику эквивалентных классов?&lt;/h2&gt;
  &lt;p id=&quot;M55m&quot;&gt;Общий алгоритм:&lt;/p&gt;
  &lt;ol id=&quot;HsHR&quot;&gt;
    &lt;li id=&quot;x8ne&quot;&gt;Определить &lt;strong&gt;входные данные / параметры&lt;/strong&gt;, которые хотим тестировать.&lt;br /&gt;Например: возраст, сумма, дата, тип документа.&lt;/li&gt;
    &lt;li id=&quot;rXf9&quot;&gt;Для каждого параметра:&lt;/li&gt;
    &lt;ul id=&quot;e7BB&quot;&gt;
      &lt;li id=&quot;qczh&quot;&gt;выделить &lt;strong&gt;допустимые (валидные)&lt;/strong&gt; классы;&lt;/li&gt;
      &lt;li id=&quot;9BD0&quot;&gt;выделить &lt;strong&gt;недопустимые (невалидные)&lt;/strong&gt; классы.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;3NQa&quot;&gt;Из каждого класса взять &lt;strong&gt;по 1–2 представителя&lt;/strong&gt; и сделать на их основе тесты.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;tIRu&quot;&gt;📌 Пример (простой)&lt;/h2&gt;
  &lt;p id=&quot;vGhc&quot;&gt;Поле «Возраст»:&lt;br /&gt;Допустим ввод: &lt;strong&gt;от 18 до 60 включительно&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;aQiN&quot;&gt;Мы можем выделить классы:&lt;/p&gt;
  &lt;ul id=&quot;JceR&quot;&gt;
    &lt;li id=&quot;V5aO&quot;&gt;❌ Класс 1: возраст &amp;lt; 18 (например, 10, 17)&lt;/li&gt;
    &lt;li id=&quot;ZgQ1&quot;&gt;✅ Класс 2: 18–60 (например, 20, 35, 60)&lt;/li&gt;
    &lt;li id=&quot;BBuB&quot;&gt;❌ Класс 3: возраст &amp;gt; 60 (например, 61, 99)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;EILj&quot;&gt;Для тестов мы не берём все числа, а выбираем &lt;strong&gt;по одному представителю&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;CHOW&quot;&gt;
    &lt;li id=&quot;Wd2T&quot;&gt;Тест 1: возраст = 17 (недопустимый, слишком маленький)&lt;/li&gt;
    &lt;li id=&quot;VULn&quot;&gt;Тест 2: возраст = 30 (допустимый)&lt;/li&gt;
    &lt;li id=&quot;HyGA&quot;&gt;Тест 3: возраст = 65 (недопустимый, слишком большой)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;fGRl&quot;&gt;🧠 Рекомендации по выделению классов&lt;/h2&gt;
  &lt;ol id=&quot;mfzb&quot;&gt;
    &lt;li id=&quot;9sUe&quot;&gt;Если входное условие — &lt;strong&gt;диапазон&lt;/strong&gt;&lt;br /&gt;Например: от 1 до 10&lt;br /&gt;➜ 1 &lt;em&gt;допустимый&lt;/em&gt; класс: 1–10&lt;br /&gt;➜ 2 &lt;em&gt;недопустимых&lt;/em&gt;: &amp;lt;1 и &amp;gt;10&lt;/li&gt;
    &lt;li id=&quot;zXiM&quot;&gt;Если входное условие — &lt;strong&gt;набор значений&lt;/strong&gt;&lt;br /&gt;Например: статус ∈ {«новый», «в работе», «закрыт»}&lt;br /&gt;➜ по &lt;strong&gt;1 допустимому классу на каждое значение&lt;/strong&gt;&lt;br /&gt;➜ 1 общий недопустимый класс — всё остальное.&lt;/li&gt;
    &lt;li id=&quot;hshi&quot;&gt;Если условие — &lt;strong&gt;«должно быть так-то»&lt;/strong&gt;&lt;br /&gt;Например: поле обязательно для заполнения&lt;br /&gt;➜ 1 допустимый класс (поле заполнено корректно)&lt;br /&gt;➜ 1 недопустимый (пустое/некорректное значение).&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;m0rh&quot;&gt;✅ В чём польза эквивалентных классов для тестировщика?&lt;/h2&gt;
  &lt;ul id=&quot;T63A&quot;&gt;
    &lt;li id=&quot;hK3f&quot;&gt;Ты &lt;strong&gt;не перебираешь все возможные значения&lt;/strong&gt;, а проверяешь только «представителей» классов.&lt;/li&gt;
    &lt;li id=&quot;M16D&quot;&gt;Покрываешь &lt;strong&gt;все важные случаи&lt;/strong&gt;, не утопая в бесконечных вариациях.&lt;/li&gt;
    &lt;li id=&quot;wtC3&quot;&gt;Экономишь время и &lt;strong&gt;выглядишь на собесе как человек, который умеет думать системно&lt;/strong&gt;, а не просто «тыкать поля».&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;chxm&quot;&gt;2️⃣ Анализ граничных значений (Boundary Values) 📏&lt;/h1&gt;
  &lt;h2 id=&quot;bPsW&quot;&gt;🧩 Суть техники&lt;/h2&gt;
  &lt;p id=&quot;o4jA&quot;&gt;Граница — это место, где система &lt;strong&gt;переходит&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;GKKX&quot;&gt;
    &lt;li id=&quot;Cry4&quot;&gt;от «разрешено» к «запрещено»,&lt;/li&gt;
    &lt;li id=&quot;gwq6&quot;&gt;от одной скидки к другой,&lt;/li&gt;
    &lt;li id=&quot;2aso&quot;&gt;от «стаж работы слишком маленький» к «достаточный».&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;m4I1&quot;&gt;&lt;strong&gt;Техника граничных значений&lt;/strong&gt; говорит:&lt;/p&gt;
  &lt;blockquote id=&quot;SM1l&quot;&gt;Больше всего багов — на границе.&lt;br /&gt;Поэтому проверяй не только внутри диапазона, но и &lt;strong&gt;рядом с границами&lt;/strong&gt;.&lt;/blockquote&gt;
  &lt;p id=&quot;C8oT&quot;&gt;Обычно проверяют:&lt;/p&gt;
  &lt;ul id=&quot;SgAe&quot;&gt;
    &lt;li id=&quot;CQ7x&quot;&gt;значение &lt;strong&gt;чуть меньше границы&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;9wk6&quot;&gt;&lt;strong&gt;саму границу&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;BVrD&quot;&gt;значение &lt;strong&gt;чуть больше границы&lt;/strong&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;mArc&quot;&gt;🔢 Что такое «ШАГ» и зачем он нужен?&lt;/h2&gt;
  &lt;p id=&quot;H7Hf&quot;&gt;Прежде чем применять технику, нужно понять:&lt;br /&gt;👉 &lt;strong&gt;ШАГ&lt;/strong&gt; — это минимальная разница между двумя соседними значениями.&lt;/p&gt;
  &lt;p id=&quot;LLEp&quot;&gt;Например:&lt;/p&gt;
  &lt;ul id=&quot;cVv8&quot;&gt;
    &lt;li id=&quot;SM6t&quot;&gt;Если суммы в корзине идут по целым рублям → шаг = 1 рубль.&lt;/li&gt;
    &lt;li id=&quot;f4pD&quot;&gt;Если цены могут быть с копейками → шаг = 0.01.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Ff9Q&quot;&gt;🍏 Пример с корзиной и скидками&lt;/h2&gt;
  &lt;p id=&quot;uNI2&quot;&gt;Условие:&lt;/p&gt;
  &lt;ul id=&quot;t0O6&quot;&gt;
    &lt;li id=&quot;zh0X&quot;&gt;До 100 рублей — &lt;strong&gt;0% скидки&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;skWR&quot;&gt;От 100 рублей и выше — &lt;strong&gt;5% скидки&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;mOnO&quot;&gt;🇷🇺 Российский интернет-магазин&lt;/h3&gt;
  &lt;p id=&quot;ISBI&quot;&gt;Цены только в рублях, &lt;strong&gt;без копеек&lt;/strong&gt; → шаг = 1 рубль.&lt;/p&gt;
  &lt;p id=&quot;Ufos&quot;&gt;Граница — &lt;strong&gt;100 рублей&lt;/strong&gt;. Значит тестируем:&lt;/p&gt;
  &lt;ul id=&quot;LcM5&quot;&gt;
    &lt;li id=&quot;gaZM&quot;&gt;99 — ещё нет скидки&lt;/li&gt;
    &lt;li id=&quot;YhIt&quot;&gt;100 — уже должна быть 5%&lt;/li&gt;
    &lt;li id=&quot;Gbtf&quot;&gt;101 — всё ещё 5%&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;Btva&quot;&gt;🇧🇾 Белорусский интернет-магазин&lt;/h3&gt;
  &lt;p id=&quot;6b5u&quot;&gt;Цены в рублях и копейках → шаг = 0.01.&lt;/p&gt;
  &lt;p id=&quot;oMuQ&quot;&gt;Проверяем:&lt;/p&gt;
  &lt;ul id=&quot;7njH&quot;&gt;
    &lt;li id=&quot;nhiu&quot;&gt;99.99 — 0%&lt;/li&gt;
    &lt;li id=&quot;R1tD&quot;&gt;100.00 — 5%&lt;/li&gt;
    &lt;li id=&quot;pKqL&quot;&gt;100.01 — 5%&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;9dMb&quot;&gt;👉 На собеседовании &lt;strong&gt;обязательно проговаривай шаг&lt;/strong&gt;:&lt;/p&gt;
  &lt;blockquote id=&quot;kURS&quot;&gt;«Если шаг = 1 рубль, проверю 99, 100 и 101.&lt;br /&gt;Если есть копейки, проверю 99.99, 100.00 и 100.01».&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Cw5R&quot;&gt;🧠 О чём гласит техника граничных значений?&lt;/h2&gt;
  &lt;p id=&quot;aSrk&quot;&gt;Коротко:&lt;/p&gt;
  &lt;blockquote id=&quot;8mSv&quot;&gt;Ошибки чаще всего живут на границах диапазонов.&lt;br /&gt;Поэтому, кроме обычных значений, &lt;strong&gt;обязательно тестируй значения на границе и рядом с ней&lt;/strong&gt;.&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;44h7&quot;&gt;&lt;/h1&gt;
  &lt;figure id=&quot;ll8m&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b3/15/b3158690-1fc4-4033-a0b0-b34d37940efd.jpeg&quot; width=&quot;1536&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;M3Jj&quot;&gt;3️⃣ Попарное тестирование (Pairwise) 🤝&lt;/h2&gt;
  &lt;h2 id=&quot;k2zz&quot;&gt;🧩 Что это вообще такое?&lt;/h2&gt;
  &lt;p id=&quot;HMWn&quot;&gt;Попарное тестирование — это техника, которая помогает &lt;strong&gt;проверить все пары параметров&lt;/strong&gt;, но &lt;strong&gt;не перебирать все комбинации целиком&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;SAvq&quot;&gt;Когда у тебя много параметров (цвет, размер, тип доставки, способ оплаты и т.д.), количество всех комбинаций может быть огромным.&lt;/p&gt;
  &lt;p id=&quot;Vg9H&quot;&gt;👉 Попарное тестирование говорит:&lt;/p&gt;
  &lt;blockquote id=&quot;le8H&quot;&gt;«Большинство багов проявляются при взаимодействии &lt;strong&gt;двух параметров&lt;/strong&gt;.&lt;br /&gt;Поэтому протестируем &lt;strong&gt;все пары&lt;/strong&gt; комбинаций, а не полный перебор».&lt;/blockquote&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;OMaA&quot;&gt;🧯 Когда применять попарное тестирование?&lt;/h2&gt;
  &lt;p id=&quot;FUXv&quot;&gt;Используем, когда:&lt;/p&gt;
  &lt;ul id=&quot;l9PM&quot;&gt;
    &lt;li id=&quot;aUD9&quot;&gt;Есть &lt;strong&gt;несколько параметров с несколькими вариантами&lt;/strong&gt; (цвет, размер, тип товара, страна, способ доставки).&lt;/li&gt;
    &lt;li id=&quot;mJYC&quot;&gt;Полный перебор комбинаций даёт десятки/сотни сценариев.&lt;/li&gt;
    &lt;li id=&quot;13D4&quot;&gt;Нужно:&lt;/li&gt;
    &lt;ul id=&quot;8Ph3&quot;&gt;
      &lt;li id=&quot;F4v1&quot;&gt;сократить количество тестов,&lt;/li&gt;
      &lt;li id=&quot;aiEK&quot;&gt;&lt;strong&gt;но всё равно покрыть большинство важных комбинаций&lt;/strong&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ZAKX&quot;&gt;Типичные случаи:&lt;/p&gt;
  &lt;ul id=&quot;FTBB&quot;&gt;
    &lt;li id=&quot;ovIO&quot;&gt;формы с множеством выпадающих списков;&lt;/li&gt;
    &lt;li id=&quot;Z5j6&quot;&gt;фильтры (каталог товаров);&lt;/li&gt;
    &lt;li id=&quot;DQau&quot;&gt;настройки, где пользователь может задавать разные комбинации параметров.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;BfZs&quot;&gt;✅ В чём польза для тестировщика?&lt;/h2&gt;
  &lt;ul id=&quot;qbOO&quot;&gt;
    &lt;li id=&quot;H6kf&quot;&gt;📉 &lt;strong&gt;Меньше тест-кейсов&lt;/strong&gt;, чем при полном переборе.&lt;/li&gt;
    &lt;li id=&quot;V4yD&quot;&gt;📈 &lt;strong&gt;Больше покрытия&lt;/strong&gt;, чем если «тыкать наугад».&lt;/li&gt;
    &lt;li id=&quot;Z88S&quot;&gt;💰 Экономия времени и ресурсов.&lt;/li&gt;
    &lt;li id=&quot;4asO&quot;&gt;🔍 Часто позволяет найти баги, которые не видно одиночными проверками.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;BTUY&quot;&gt;⚠️ Недостатки&lt;/h2&gt;
  &lt;ul id=&quot;yA9n&quot;&gt;
    &lt;li id=&quot;Jz95&quot;&gt;Не покрывает &lt;strong&gt;все&lt;/strong&gt; сложные комбинации (например, когда баг возникает при одновременном сочетании 3+ параметров).&lt;/li&gt;
    &lt;li id=&quot;aHqK&quot;&gt;Нужно &lt;strong&gt;грамотно выбрать параметры и их значения&lt;/strong&gt;, иначе можно упустить важные случаи.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;BZA8&quot;&gt;🛠 Инструмент для попарного тестирования&lt;/h2&gt;
  &lt;p id=&quot;3DmW&quot;&gt;Есть удобный онлайн-сервис:&lt;br /&gt;👉 &lt;code&gt;https://pairwise.teremokgames.com&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;ORfg&quot;&gt;Что можно сделать:&lt;/p&gt;
  &lt;ol id=&quot;doqx&quot;&gt;
    &lt;li id=&quot;w263&quot;&gt;Вбить:&lt;/li&gt;
    &lt;ul id=&quot;PUgi&quot;&gt;
      &lt;li id=&quot;aSZO&quot;&gt;параметры,&lt;/li&gt;
      &lt;li id=&quot;ixG5&quot;&gt;варианты значений.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;LXX1&quot;&gt;Нажать «сгенерировать».&lt;/li&gt;
    &lt;li id=&quot;9aGS&quot;&gt;Получить &lt;strong&gt;короткий список сценариев&lt;/strong&gt;, которые покрывают все пары параметров.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;6wLH&quot;&gt;Ты можешь:&lt;/p&gt;
  &lt;ul id=&quot;KtRI&quot;&gt;
    &lt;li id=&quot;fw9u&quot;&gt;сделать тестовый пример,&lt;/li&gt;
    &lt;li id=&quot;TizK&quot;&gt;сохранить набор сценариев,&lt;/li&gt;
    &lt;li id=&quot;9K6P&quot;&gt;приложить файл или скриншот в свою карточку по учебному проекту.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;XAto&quot;&gt;4️⃣ Таблица переходов / схема состояний 🔄&lt;/h1&gt;
  &lt;h2 id=&quot;RBSN&quot;&gt;🧩 Что такое схема переходов и состояний?&lt;/h2&gt;
  &lt;p id=&quot;HoKa&quot;&gt;Любой объект в системе может:&lt;/p&gt;
  &lt;ul id=&quot;XG1G&quot;&gt;
    &lt;li id=&quot;OYpf&quot;&gt;находиться в разных &lt;strong&gt;состояниях&lt;/strong&gt;,&lt;/li&gt;
    &lt;li id=&quot;Hnd7&quot;&gt;переходить из одного состояния в другое &lt;strong&gt;по событию&lt;/strong&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;QcKN&quot;&gt;&lt;strong&gt;Схема переходов и состояний&lt;/strong&gt; — это модель, которая показывает:&lt;/p&gt;
  &lt;ul id=&quot;yLbl&quot;&gt;
    &lt;li id=&quot;Zbdz&quot;&gt;какие состояния бывают,&lt;/li&gt;
    &lt;li id=&quot;kM9x&quot;&gt;какие события к каким переходам приводят,&lt;/li&gt;
    &lt;li id=&quot;KGrw&quot;&gt;какие переходы запрещены.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Xdlh&quot;&gt;📌 Пример: документ в системе&lt;/p&gt;
  &lt;p id=&quot;16Np&quot;&gt;Состояния:&lt;/p&gt;
  &lt;ol id=&quot;p2wT&quot;&gt;
    &lt;li id=&quot;yI0K&quot;&gt;«Не создан»&lt;/li&gt;
    &lt;li id=&quot;iDFQ&quot;&gt;«В разработке»&lt;/li&gt;
    &lt;li id=&quot;SHJL&quot;&gt;«Утверждён»&lt;/li&gt;
    &lt;li id=&quot;JB4s&quot;&gt;«Устаревший»&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;POqj&quot;&gt;Переходы:&lt;/p&gt;
  &lt;ul id=&quot;kJlX&quot;&gt;
    &lt;li id=&quot;RS6j&quot;&gt;«Создать» → из «Не создан» в «В разработке»&lt;/li&gt;
    &lt;li id=&quot;6AgR&quot;&gt;«Утвердить» → из «В разработке» в «Утверждён»&lt;/li&gt;
    &lt;li id=&quot;d0m5&quot;&gt;«Аннулировать» → из «Утверждён» в «Устаревший»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;QEjX&quot;&gt;Техника «таблица переходов» позволяет:&lt;/p&gt;
  &lt;ul id=&quot;nH1e&quot;&gt;
    &lt;li id=&quot;kDwc&quot;&gt;явно описать эти состояния и переходы,&lt;/li&gt;
    &lt;li id=&quot;0LFs&quot;&gt;проверить, что &lt;strong&gt;невозможные переходы не происходят&lt;/strong&gt; (например, сразу из «Не создан» в «Утверждён»).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;Pf5E&quot;&gt;5️⃣ Таблица принятия решений 🧾&lt;/h1&gt;
  &lt;h2 id=&quot;rL9C&quot;&gt;🧩 Суть техники&lt;/h2&gt;
  &lt;p id=&quot;1fj8&quot;&gt;Иногда система принимает решение &lt;strong&gt;на основе нескольких условий&lt;/strong&gt;.&lt;br /&gt;Например:&lt;/p&gt;
  &lt;ul id=&quot;I6yz&quot;&gt;
    &lt;li id=&quot;F2tD&quot;&gt;пользователь зашёл?&lt;/li&gt;
    &lt;li id=&quot;SFm7&quot;&gt;он админ?&lt;/li&gt;
    &lt;li id=&quot;NDqO&quot;&gt;подписка активна?&lt;/li&gt;
    &lt;li id=&quot;rAFa&quot;&gt;баланс &amp;gt; 0?&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;mcu0&quot;&gt;&lt;strong&gt;Таблица принятия решений&lt;/strong&gt; помогает:&lt;/p&gt;
  &lt;ul id=&quot;kRr4&quot;&gt;
    &lt;li id=&quot;UTwu&quot;&gt;выписать все важные условия,&lt;/li&gt;
    &lt;li id=&quot;33iY&quot;&gt;указать возможные комбинации «да/нет»,&lt;/li&gt;
    &lt;li id=&quot;a6hy&quot;&gt;прописать, какое действие выполняется в каждой комбинации.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;0Tpc&quot;&gt;Это очень удобно, когда логика сложная и много веток.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;93QG&quot;&gt;6️⃣ Прогнозирование ошибок (Error Guessing) 🧙‍♀️&lt;/h1&gt;
  &lt;h2 id=&quot;QS8q&quot;&gt;🧩 Что это такое?&lt;/h2&gt;
  &lt;p id=&quot;jMhP&quot;&gt;Это техника, основанная &lt;strong&gt;на опыте тестировщика&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;FGiZ&quot;&gt;Тестировщик задаёт себе вопросы:&lt;/p&gt;
  &lt;ul id=&quot;45ll&quot;&gt;
    &lt;li id=&quot;Nj3H&quot;&gt;«Где тут разработчик мог накосячить?»&lt;/li&gt;
    &lt;li id=&quot;ztaF&quot;&gt;«В этом месте обычно забывают проверять пустые значения?»&lt;/li&gt;
    &lt;li id=&quot;Grt9&quot;&gt;«В прошлых проектах в этих сценариях часто вылезали баги».&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;I33b&quot;&gt;Он вспоминает:&lt;/p&gt;
  &lt;ul id=&quot;Jwqr&quot;&gt;
    &lt;li id=&quot;oGjD&quot;&gt;прошлые баги,&lt;/li&gt;
    &lt;li id=&quot;pBty&quot;&gt;типичные ошибки,&lt;/li&gt;
    &lt;li id=&quot;FtqM&quot;&gt;особенности этой системы.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;xleq&quot;&gt;И специально делает тесты &lt;em&gt;именно под эти предполагаемые слабые места&lt;/em&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;EQNf&quot;&gt;7️⃣ Причинно-следственный анализ (Cause–Effect) 🧬&lt;/h1&gt;
  &lt;h2 id=&quot;ZGjA&quot;&gt;🧩 Суть техники&lt;/h2&gt;
  &lt;p id=&quot;k6QE&quot;&gt;Мы рассматриваем систему как набор:&lt;/p&gt;
  &lt;ul id=&quot;hpwI&quot;&gt;
    &lt;li id=&quot;JGia&quot;&gt;&lt;strong&gt;причин (conditions)&lt;/strong&gt; — условия / входные данные,&lt;/li&gt;
    &lt;li id=&quot;FrCJ&quot;&gt;&lt;strong&gt;следствий (effects)&lt;/strong&gt; — результаты / реакции системы.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ZPT9&quot;&gt;Задача:&lt;/p&gt;
  &lt;blockquote id=&quot;YL1f&quot;&gt;Найти связь:&lt;br /&gt;«какие комбинации причин приводят к каким следствиям».&lt;/blockquote&gt;
  &lt;p id=&quot;1K5X&quot;&gt;Например:&lt;/p&gt;
  &lt;ul id=&quot;ejsR&quot;&gt;
    &lt;li id=&quot;AWPI&quot;&gt;Причина: логин и пароль введены правильно&lt;br /&gt;➜ Следствие: пользователь авторизован&lt;/li&gt;
    &lt;li id=&quot;slJf&quot;&gt;Причина: пароль неправильный&lt;br /&gt;➜ Следствие: ошибка авторизации&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Nvdi&quot;&gt;Техника помогает:&lt;/p&gt;
  &lt;ul id=&quot;CbJ4&quot;&gt;
    &lt;li id=&quot;QG0b&quot;&gt;системно перебрать комбинации условий;&lt;/li&gt;
    &lt;li id=&quot;OWmf&quot;&gt;понять, где не хватает проверки;&lt;/li&gt;
    &lt;li id=&quot;2miq&quot;&gt;увидеть, что некоторые комбинации не обработаны вообще.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;N3d6&quot;&gt;8️⃣ Исследовательское тестирование 🕵️‍♀️&lt;/h1&gt;
  &lt;h2 id=&quot;sTCr&quot;&gt;🧩 Что это такое?&lt;/h2&gt;
  &lt;p id=&quot;FMbH&quot;&gt;&lt;strong&gt;Исследовательское тестирование&lt;/strong&gt; — это когда ты:&lt;/p&gt;
  &lt;ul id=&quot;AAUu&quot;&gt;
    &lt;li id=&quot;oAGJ&quot;&gt;не следуешь заранее написанным тест-кейсам,&lt;/li&gt;
    &lt;li id=&quot;Nlh8&quot;&gt;а сам изучаешь систему «живьём»,&lt;/li&gt;
    &lt;li id=&quot;p4K4&quot;&gt;строишь гипотезы,&lt;/li&gt;
    &lt;li id=&quot;ZKAE&quot;&gt;сразу же проверяешь их.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;kcVZ&quot;&gt;Это смесь:&lt;/p&gt;
  &lt;ul id=&quot;uhvV&quot;&gt;
    &lt;li id=&quot;nFum&quot;&gt;любопытства,&lt;/li&gt;
    &lt;li id=&quot;bk21&quot;&gt;опыта,&lt;/li&gt;
    &lt;li id=&quot;QFqL&quot;&gt;логики.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;FAfJ&quot;&gt;Обычно:&lt;/p&gt;
  &lt;ul id=&quot;olwP&quot;&gt;
    &lt;li id=&quot;A9Sf&quot;&gt;используют, когда документа мало,&lt;/li&gt;
    &lt;li id=&quot;5a9t&quot;&gt;или продукт сильно меняется,&lt;/li&gt;
    &lt;li id=&quot;h4Ia&quot;&gt;или нужно быстро «прощупать» новую фичу.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;a6FH&quot;&gt;Но даже в исследовательском тестировании &lt;strong&gt;техники тест-дизайна всё равно в голове&lt;/strong&gt;: ты всё равно мысленно используешь эквивалентные классы, границы, сценарии, переключаешь состояния и пр.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;QPFE&quot;&gt;9️⃣ Небольшой конспект техник (как шпаргалка) 📚&lt;/h1&gt;
  &lt;ul id=&quot;AxOp&quot;&gt;
    &lt;li id=&quot;ZrbM&quot;&gt;⚖️ &lt;strong&gt;Эквивалентное разбиение&lt;/strong&gt;&lt;br /&gt;Делим входные данные на классы (валидные / невалидные) и берём по одному представителю из каждого.&lt;/li&gt;
    &lt;li id=&quot;78Xj&quot;&gt;📏 &lt;strong&gt;Граничные значения&lt;/strong&gt;&lt;br /&gt;Проверяем значения &lt;strong&gt;на границах диапазона и рядом с ними&lt;/strong&gt;.&lt;br /&gt;Перед применением — обязательно определяем ШАГ.&lt;/li&gt;
    &lt;li id=&quot;SWba&quot;&gt;🌐 &lt;strong&gt;Доменный анализ&lt;/strong&gt;&lt;br /&gt;Разделение диапазона значений на поддиапазоны (домены) и выбор 1–2 значений из каждого для тестирования.&lt;/li&gt;
    &lt;li id=&quot;LexG&quot;&gt;🧙 &lt;strong&gt;Прогнозирование ошибок&lt;/strong&gt;&lt;br /&gt;Используем опыт и знание типичных багов, чтобы специально искать слабые места.&lt;/li&gt;
    &lt;li id=&quot;rtl4&quot;&gt;🧬 &lt;strong&gt;Причина / следствие&lt;/strong&gt;&lt;br /&gt;Вводим условия → смотрим результаты → проверяем связи между ними.&lt;/li&gt;
    &lt;li id=&quot;A7Ui&quot;&gt;🎭 &lt;strong&gt;Use Case тестирование&lt;/strong&gt;&lt;br /&gt;Проверяем реальные пользовательские сценарии (истории, как пользователи взаимодействуют с системой).&lt;/li&gt;
    &lt;li id=&quot;wBci&quot;&gt;🧨 &lt;strong&gt;Исчерпывающее тестирование&lt;/strong&gt;&lt;br /&gt;Проверка &lt;em&gt;всех&lt;/em&gt; комбинаций. В теории красиво, на практике почти нереально.&lt;/li&gt;
    &lt;li id=&quot;xXeZ&quot;&gt;🤝 &lt;strong&gt;Попарное тестирование (Pairwise)&lt;/strong&gt;&lt;br /&gt;Строим тесты так, чтобы &lt;strong&gt;все пары параметров&lt;/strong&gt; встретились хотя бы раз.&lt;br /&gt;Сильно сокращает количество тестов.&lt;/li&gt;
    &lt;li id=&quot;cJ7u&quot;&gt;🔄 &lt;strong&gt;Состояния и переходы&lt;/strong&gt;&lt;br /&gt;Моделируем, в каких состояниях может быть объект и как он переходит из одного в другое.&lt;/li&gt;
    &lt;li id=&quot;GEJt&quot;&gt;🧾 &lt;strong&gt;Таблица принятия решений&lt;/strong&gt;&lt;br /&gt;Упорядочиваем сложную бизнес-логику с несколькими условиями и результатами в виде таблицы.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h1 id=&quot;T9S1&quot;&gt;🧷 Главное, что должен вынести новичок&lt;/h1&gt;
  &lt;ol id=&quot;FzZ9&quot;&gt;
    &lt;li id=&quot;ORyk&quot;&gt;&lt;strong&gt;Тест-дизайн — это не «страшная теория», а способ думать о тестах умно.&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;WvhM&quot;&gt;&lt;strong&gt;Техники&lt;/strong&gt; помогают:&lt;/li&gt;
    &lt;ul id=&quot;FP2O&quot;&gt;
      &lt;li id=&quot;ISI3&quot;&gt;уменьшать количество тестов,&lt;/li&gt;
      &lt;li id=&quot;Wx6d&quot;&gt;повышать качество проверок,&lt;/li&gt;
      &lt;li id=&quot;M6Fl&quot;&gt;находить серьёзные баги быстрее.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;mqsw&quot;&gt;На собеседовании важно:&lt;/li&gt;
    &lt;ul id=&quot;ZAjW&quot;&gt;
      &lt;li id=&quot;vpnh&quot;&gt;уметь объяснить &lt;strong&gt;эквивалентные классы&lt;/strong&gt;,&lt;/li&gt;
      &lt;li id=&quot;Fh6s&quot;&gt;&lt;strong&gt;граничные значения&lt;/strong&gt; (обязательно упомянуть шаг),&lt;/li&gt;
      &lt;li id=&quot;nf52&quot;&gt;&lt;strong&gt;попарное тестирование&lt;/strong&gt;,&lt;/li&gt;
      &lt;li id=&quot;u5LF&quot;&gt;&lt;strong&gt;таблицу состояний / переходов&lt;/strong&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;iSUo&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p id=&quot;Qaz7&quot;&gt;дополнительная информация тут: &lt;/p&gt;
  &lt;p id=&quot;hsxM&quot;&gt;&lt;a href=&quot;https://youtu.be/7a7vGZqwtCA?si=4T6kTpEieVlMjiOB&quot; target=&quot;_blank&quot;&gt;https://youtu.be/7a7vGZqwtCA?si=4T6kTpEieVlMjiOB&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;t6OO&quot;&gt;&lt;br /&gt;полезная шпаргалка с примерами: &lt;/p&gt;
  &lt;p id=&quot;zfQh&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/740026/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/articles/740026/&lt;/a&gt;&lt;/p&gt;

</content></entry></feed>