- PVSM.RU - https://www.pvsm.ru -
Привет всем заглянувшим!
В этой статье я поделюсь опытом автоматизации API‑тестирования связкой Postman + Newman, но с небольшим "секретным ингредиентом". Мы не просто будем запускать коллекции в Jenkins напрямую, а используем универсальный Python‑скрипт, который превращает стандартный прогон в мощный инструмент мониторинга.
Обычно Newman выдает довольно сухие отчеты. Мой скрипт выступает в роли умной прослойки: он обрабатывает результаты тестов на статус‑коды, собирает данные и упаковывает их в наглядный Allure‑отчет. Более того, здесь добавлена функция почтовых уведомлений, чтобы контролировать состояние системы, не заходя в Jenkins.
Такой метод идеально подходит для регрессионного тестирования микросервисов. Настроили триггеры - и система сама проверяет код после каждого коммита или по расписанию, отправляя структурированный отчет. Боитесь, что настройка будет слишком сложной? Не стоит!
Ниже я представлю суперподробную пошаговую инструкцию для Windows и MacOS, по которой настроить прогон в Jenkins "под ключ" сможет даже человек, только недавно пришедший в IT.
Прежде всего прикреплю ссылки на сам скрипт и сопутствующие файлы.env [1]. Также, у меня уже есть готовые коллекция и окружение postman, которые я буду использовать в качестве примера. Ссылки на них также прикрепила. Обратите внимание: в коллекции присутствуют 2 запроса, в ответе на которые мы ожидаем увидеть не 200, а иной код
Здесь вы найдете все 5 файлов, необходимых для дальнейшей работы:
Example_collection.postman_collection.json [2] - коллекция запросов для Postman
test.postman_environment.json [3] - файл окружения (Environment) для Postman
code.py [4] - скрипт для запуска коллекции Postman
env.email [5] - файл с шаблонами переменных для почты
env.paths [6] - файл с шаблонами переменных для путей
Вы можете скачать данные файлы по отдельности или загрузить одним архивом, перейдя по первой ссылке, и нажав Code => Download ZIP на главной странице репозитория.
Обратите внимание! После скачивания в начале названий файлов env.email и env.paths необходимо проставить точки (.env.email и.env.paths), иначе эти файлы просто не запустятся.
В остальном они полностью готовые и рабочие - осталось только подставить в них нужные значения. Однако, если вы захотите как‑то изменить или доработать предоставленный готовый скрипт - ваше право.
Итак, перейдем к делу.
Перед тем, как приступать к созданию автотестов, необходимо провести подготовку:
установить все необходимые сопутствующие инструменты;
создать коллекцию и окружение в Postman и экспортировать их;
внести необходимые изменения в скрипт и файлы.env;
создать виртуальное окружение и проверить работоспособность скрипта.
Это обязательная часть процесса, иначе тесты не запустятся. Да и нечего будет запускать.
Это необходимо для последующей установки Newman. Также, в дальнейшем, когда Jenkins будет запускать Newman, он будет использовать именно Node.js для интерпретации и выполнения JavaScript‑кода, содержащегося в коллекциях Postman и скриптах тестов.
Перейдите на официальный сайт Node.js [7]и скачайте установщик для вашей ОС.
Установите Node.js, следуя инструкциям установщика. Это также установит npm (Node Package Manager)
Проверьте установку Node.js и npm в командной строке при помощи следующих команд командной строки:
node -v
npm -v
Newman - это инструмент командной строки, который позволяет запускать коллекции Postman непосредственно из нее. Для запуска тестов Postman в Jenkins вы указываете команду для запуска Newman, которая, в свою очередь, использует Node.js для выполнения этих тестов.
Важное примечание по правам доступа:
|
• Для Windows: открывайте командную строку (cmd) или PowerShell от имени администратора.
|
• Для macOS: если при выполнении команд ниже вы увидите ошибку "EACCES: permission denied", добавьте слово sudo в начало команды (например, |
В командной строке введите следующую команду: npm install -g newman
Проверьте установку командойnewman -v
Установите Allure‑репортер для генерации Allure Results командойnpm install -g newman-reporter-allure
Проверить установку можно командойnpm list -g newman-reporter-allure
Это необходимо для того, чтобы в дальнейшем без проблем формировать Allure отчет
Установите newman‑reporter‑json командойnpm install -g newman-reporter-json
Проверить установку можно командойnpm list -g newman-reporter-json
Он необходим для дальнейшего формирования json‑отчетов о прогоне коллекции. Эти отчеты понадобятся для создания письма с результатами прогона.
|
Для пользователей Windows Скачайте и установите Python с официального сайта [8]. Важный нюанс при установке: когда запустите инсталлятор, обязательно поставьте галочку "Add Python to PATH" в самом первом окне. Это избавит вас от 90% проблем с настройкой. Проверить установку командой Если появится ошибка, то необходимо добавить путь к Python в переменную окружения PATH на вашем ПК. Вот как это сделать: Найдите, папку, в которую установлен Python. Скопируйте этот путь. Откройте "Панель управления" и перейдите в "Система и безопасность" >"Система". Нажмите на "Дополнительные параметры системы" справа. В открывшемся окне нажмите на кнопку "Переменные среды". В разделе "Системные переменные" найдите переменную с именем Path и выберите её, затем нажмите "Изменить". В открывшемся окне нажмите "Создать" и вставьте скопированный путь к папке Python Нажмите "ОК" во всех окнах, чтобы сохранить изменения. Перезапустите командную строку: После внесения изменений в переменные окружения закройте и снова откройте командную строку, чтобы изменения вступили в силу. Проверьте установку: Введите команду
|
Для пользователей macOS Прежде чем мы начнем ставить Python, Java и всё остальное, нужно установить Homebrew. Это инструмент, который возьмет на себя всю рутину по установке программ и настройке путей. 1. Откройте Терминал 2. Скопируйте и вставьте туда следующую команду: 3. Дождитесь окончания (вас могут попросить ввести пароль от Mac - при вводе символы не будут отображаться, это нормально 4. В конце установки в терминале могут появиться 2–3 строчки под заголовком "Next steps". Скопируйте их и выполните там же в терминале - это нужно, чтобы команда brew стала активной 5. Проверьте установку: А теперь перейдем непосредственно к установке Python через менеджер пакетов Homebrew: 1. Откройте Терминал и введите: 2. Проверьте установку командой Если команда python3 не находится, необходимо добавить путь к Python в переменную окружения PATH на вашем ПК. Вот как это сделать: • Узнайте, где лежит ваш python3 командой • Добавьте путь в файл конфигурации вашего терминала (обычно это.zshrc или.bash_profile) командой ("/usr/local/bin" - это стандартный путь. Замените его на тот, что выдала команда which, если он отличается) далее введите команду Проверьте установку командой |
Необходима для последующей установки Jenkins.
Важно: Jenkins официально поддерживает только Java 17 и 21, поэтому нужно скачать одну из этих версий (изначально была Java 24, и Jenkins выдавал ошибку)
|
Для пользователей Windows: Скачать и установить её с официального сайта Oracle [9] или использовать OpenJDK. После установки Java необходимо установить переменную окружения JAVA_HOME, а также внести изменения в переменную окружения PATH на вашем ПК. Вот как это сделать: Проверьте установку командой |
Для пользователей macOS: 1. Откройте Терминал и введите команду для установки OpenJDK 17: 2. Настройка JAVA_HOME. На Mac система сама умеет находить путь к Java, но для Jenkins и других инструментов лучше прописать его в профиль. * Откройте файл настроек терминала: * Добавьте в конец файла следующую строку:
(Если установили 21-ю версию, замените ‑v 17 на ‑v 21) * Нажмите Control+O, Enter (сохранить) и Control+X (выйти). * Примените изменения: 3. Проверьте установку командой
|
Завершающий штрих в нашей подготовке. Если Newman - это "двигатель", который прогоняет тесты, то Allure - это "художник", который превращает сухие цифры и логи в красивые, понятные графики и отчеты.
|
Для пользователей Windows: 1. Скачайте последнюю версию с официального сайта https://github.com/allure‑framework/allure2/releases [10]. Выберите версию, подходящую для вашей операционной системы (например, allure-2.XX.X.zip [11] для Windows) 2. Распакуйте скачанный архив в удобное место. 3. Добавьте каталог с исполняемым bin‑файлом allure в системную переменную PATH, чтобы Jenkins мог его найти. (Как добавить путь в переменную PATH уже описывалось выше, при установке Python и Java. Здесь все по аналогии) 4. Проверьте установку Allure Commandline: перезапустите или откройте новую командную строку, и выполните команду |
Для пользователей macOS: Если вы уже установили Homebrew (как мы делали для Python и Java), установка займет ровно одну секунду. 1. Откройте Терминал и введите: 2. Проверьте установку:
|
Перейдите на официальный сайт Jenkins. [12]
Скачайте установочный файл (.war файл и для Windows, и для macOS)

В командной строке перейдите в директорию с вашим war‑файлом
|
• Windows: |
• macOS: |
Запустите Jenkins с помощью следующей команды:java -jar jenkins.war
Не закрывайте это окно! Jenkins работает только пока запущен этот процесс
Для последующих работ с командной строкой откройте ее в новом окне
Получите секретный пароль. При запуске Jenkins он сохранился на вашем устройстве.

Найдите файл initialAdminPassword на вашем устройстве по следующему пути:
|
* Windows: |
* macOS: /Users/(имя_пользователя)/.jenkins/secrets/initialAdminPassword |
Также пароль отображается и при первичном запуске Jenkins в терминале:
скопируйте пароль
В поле "пароль" введите скопированный пароль
Установите рекомендованные плагины (окно слева)
Следуйте дальнейшей инструкции по созданию админа
Все последующие входы в Jenkins будут осуществляться следующим образом:
• Запускаем Jenkins из командной строки с помощью команд:
|
для Windows |
для macOS |
java -jar jenkins.war
• В браузере переходим по адресу http://localhost:8080 с использованием логина и пароля, установленными при создании админа
Настройте переменную PATH в глобальных настройках Jenkins - это критически важный шаг. Без этого Jenkins не будет знать, где искать команды newman, python или allure, даже если вы установили их на сам компьютер.%PATH% - это существующая переменная окружения, которая уже содержит список директорий, где операционная система ищет исполняемые файлы. Вот как это сделать:
Главная страница => «настроить Jenkins» => конфигурации глобальных настроек и путей => глобальные настройки => переменные среды => добавить данные
|
Для пользователей Windows: • Имя: PATH • Значение: (Пример: C:Program Filesnodejs;%PATH%) Разделитель: Используется точка с запятой;. На данный момент указано 2 значения: С:путькпапкегдеустановленаNode.js и системная переменная%PATH%. Их обязательно нужно разделить знаком ";". Если в дальнейшем в переменную PATH нужно будет добавить еще какие‑то значения, то их тоже необходимо будет разделить знаком ";". |
Для пользователей macOS: • Имя: PATH • Значение: Разделитель: Используется двоеточие:.
|
=> сохранить
Установите Allure Jenkins Plugin:
• В Jenkins перейдите в Manage Jenkins => Manage Plugins.
• Перейдите на вкладку "Available".
• В поле поиска введите "Allure" и найдите "Allure Jenkins Plugin".
• Установите плагин и перезапустите Jenkins в командной строке:
ctrl+C
java -jar jenkins.war
Теперь необходимо настроить Allure Commandline в Jenkins:
Главная страница Jenkins => Manage Jenkins => Tools => Листаем страницу до конца вниз => Установки Allure Commandline => Добавить Allure Commandline
В поле "имя" введите "Allure Commandline". Чекбокс "Устанавливать автоматически" активирован по умолчанию. В поле "Версия" из выпадающего списка выберете самую последнюю версию

Нажмите на кнопки применить — сохранить
А также настройте переменную JAVA_HOME:
Настроить Jenkins => Tools => Установки JDK => Добавить JDK
‑В поле "Имя" введите любое понятное имя, например Java17
‑Снимите галочку с пункта Install automatically
‑В поле JAVA_HOME введите вручную путь к вашей Java. Вот как его найти:
|
Для пользователей Windows: В терминале введите команду Обычно путь выглядит таким образом: (Важно: нам нужен путь без папки bin на конце). |
Для пользователей macOS: В терминале введите команду: Обычно путь выглядит таким образом: |
Далее нажмите на кнопки применить - сохранить.
Здесь подробно расписывать, как создавать коллекцию в Postman со всеми переменными и иже с ними я не буду, так как это совсем другая история… Опишу вкратце:
Создайте в Postman локальное окружение для коллекций (или используйте ваше текущее)
Добавьте в локальное окружение переменные, необходимые для обращения к методу (либо можно прописать их создание в скриптах к запросам)
Создайте коллекцию, присвойте ей имя.
Добавьте методы, которые относятся к этой коллекции.
В каждом методе создайте скрипт, который будет выполнять проверку кода ответа. Это элементарные тесты, которые даже есть в сниппетах. (Метод => Scripts => Post‑responce на новой версии Postman, и вкладка tests на старых версиях Postman). На основе проверки этих кодов и простроен весь принцип дальнейшего тестирования
В прикрепленной коллекции уже имеются скрипты с тестами на код ответа. В будущем их можно будет взять за основу при создании собственных коллекций.
Расположите методы в логическом порядке выполнения
Создайте папку, в которой будет храниться проект, и экспортируйте в нее окружение и коллекцию.
Важный момент: Коллекция, окружение, а также папка, в котором будет храниться проект (и путь к ней) должны называться на латинице! Дело в том, что на некоторых устройствах системные настройки не позволяют передавать русские буквы в Newman через командную строку, и вам постоянно будут прилетать ошибки. Хотя, казалось, бы такая мелочь…
Для удобства редактирования Python‑скрипта и файлов.env можете скачать Visual studio code [14], так как редактировать эти файлы в обычном текстовом редакторе не выйдет!
Пару слов о файлах.env. Что это, и для чего:
Файлы.env (сокращение от "environment" - окружение) нужны для хранения конфигурационных данных вашего приложения отдельно от кода. Они играют ключевую роль в управлении параметрами, которые могут меняться в зависимости от среды, в которой запускается ваше приложение.
Преимущества использования файлов.env:
• Безопасность: Предотвращают попадание секретных данных в систему контроля версий.
• Гибкость: Позволяют легко менять конфигурацию приложения для разных сред.
• Удобство: Вместо того, чтобы вносить правки с данными в сам скрипт, достаточно сделать это в файлах.env
В папку с проектом, где уже лежат экспортированные окружение и коллекция, сохраните указанные выше файлы env.paths, env.email и code.py
Измените названия файлов env.paths и env.email, чтобы они начинались с точки, иначе файлы не запустятся. А вот файл со скриптом для удобства лучше переименовать по имени того объекта, который мы тестируем. Не забываем, что, если и присваиваем имя, то только на латинице.
В файле .env.email внесите изменения согласно подсказкам. Как получить пароль приложения подробно расписано в разделе "примечания" в конце статьи.
Вместо знаков ХХХХХХХ введите свои данные
В файле .env.paths замените пути к файлам коллекции и окружения, а также укажите путь к файлу newman.cmd.
Путь к нему можно посмотреть командой
|
Для Windows: |
Для macOS: |
В переменной NEWMAN_PATH замените путь от знака "=" до конца строки на путь, который вы получили при помощи команды в терминале
В переменной COLLECTION_PATH замените путь от знака "=" до "Название коллекции.postman_collection.json" на путь к директории с вашим проектом. "Название коллекции.postman_collection.json" в конце строки замените на название файла с вашей коллекцией postman
В переменной ENVIRONMENT_PATH замените путь от знака "=" до "Название окружения.postman_environment.json" на путь к директории с вашим проектом. "Название окружения.postman_ environment.json" в конце строки замените на название файла с вашим окружением postman
|
Важное примечание для пользователей macOS: Если на Windows файлы .env.paths и .env.email без проблем сохраняются с точками в начале имени, то на macOS все не так просто: система не дает сохранить файлы, названия которых начинаются с точек. Такие файлы считаются скрытыми. Они не отображаются по умолчанию в Finder (файловом менеджере macOS) или при обычном выводе ls в терминале. Изначально при скачивании файлов.env в начале названия им автоматически подставилось "doc_<дата и время скачивания>". Как отредактировать названия: 1. Откройте Терминал. Если вы не уверены, где файл, можете сначала найти его через Finder, а затем перетащить папку с файлом в окно Терминала - терминал сам напишет путь к этой папке. 3. Переименуйте файл с помощью команды Пример: Делать это нужно после того, как вы отредактировали оба.env файла, так как после изменения названия они станут скрытыми. Чтобы увидеть их в Finder, нажмите Cmd + Shift +. (точка). Несмотря на то, что файлы будут скрытыми, это не помешает дальнейшей работе с ними |
В скрипте code.py необходимо внести изменения в 52 строке

Здесь нужно заменить путь к директории, в которой хранится проект до "\python_project\py"
! Обратите внимание на двойные слеши, а также на то, в какую сторону они наклонены. На данном изображении указывается путь к директории на Windows. Для macOS слеши наклонены в обратную сторону. И в "//python_project//py" тоже
И в строке 219 необходимо указать актуальный путь к файлу.env.email

! Здесь также стоит обратить внимание на то, что наклон слешей для macOS будет в другую сторону
На этом этапе будет создано виртуальное окружение - оно помогает избежать многих проблем, связанных с зависимостями, и делает разработку более организованной, предсказуемой и безопасной.
А также будет установлена библиотека python‑dotenv. Она нужна для того, чтобы упростить управление конфигурационными параметрами приложения, а также позволяет хранить эти параметры в отдельных файлах.env и загружать их в переменные окружения.
Перед тем как отдавать всё в руки Jenkins, важно убедиться, что наша "машина" заводится и едет на локальном уровне. Прогоним скрипт вручную. Этот этап позволит нам убедиться, что все пути в.env.paths указаны верно и Python видит все нужные библиотеки.
В командной строке перейдите в директорию с вашим проектом:
|
Windows: |
macOS: |
Создайте виртуальное окружение командой
|
Windows: |
macOS: |
В папке вашего проекта появится новая папка venv
Активируйте виртуальное окружение командой
|
Windows: |
macOS: |
Как понять, что сработало? В начале строки в терминале появится префикс (venv).
(Чтобы выйти из него позже, достаточно просто написать deactivate).
Находясь внутри активного виртуального окружения, установите библиотеку python‑dotenv при помощи команды:
|
Windows: |
macOS: |
Запустите python‑script командой
|
Windows: |
macOS: |
После запуска в консоли должно отобразиться сообщение об успешном прогоне. На почту должно прийти письмо о результатах прогона
Наконец‑то мы добрались до того, к чему так долго шли!
С главной страницы Jenkins перейдите во вкладку "создать Item"
Придумайте и введите имя проекта, нажмите "Создать задачу со свободной конфигурацией"
В общих настройках выберите пункт "расширенные", и установите флажок напротив пункта "использовать другую директорию". В появившейся строке введите путь к директории с проектом. Это делается для того, чтобы папка allure results сохранялась именно в вашу директорию, а не в какое‑то неожиданное место.
Перейдите в шаги сборки => добавить шаг сборки. Далее выбор зависит от вашей ОС:

|
Для Windows Выполнить команду Windows Далее подставляем команду:
Все пути и название скрипта необходимо заменить на действующие. |
Для macOS Выполнить команду shell Далее подставляем команду: Все пути и название скрипта необходимо заменить на действующие. |
Далее перейдите к послесборочным шагам => добавить шаг после сборки => allure report
Значение переменной Path, которое по умолчанию указано как allure‑results нужно изменить на полный путь к этой папке:
|
Windows: |
macOS: |

Нажмите "применить", затем "сохранить"
Начните сборку, нажав "собрать сейчас"

Если все тесты пройдены успешно, то в разделе "builds" напротив сборки появится зеленая галочка
Если что‑то пошло не так или прогон завешен с ошибками, то вместо галочки будет отображен красный крестик

Чтобы посмотреть, что именно пошло не так, можно открыть консоль: нажать на знак стрелки напротив сборки и выбрать "Вывод консоли"

Либо, для удобства отслеживания ошибок, можно просто открыть аллюр‑отчет, который был ранее сформирован. Для этого нужно нажать на значок Allure Report напротив сборки или выбрать его в меню, также нажав на стрелку

В аллюр‑отчете можно потыкать, и посмотреть подробнее, какие именно тесты, и каким образом были провалены
Помимо всего прочего, на почту, которая была прописана в файле.env.email, также приходит письмо о результатах прогона, и выглядит оно следующим образом:
Как мы видим, этот отчет тоже достаточно понятно описывает, что пошло не так.
Кроме того, уже непосредственно в Jenkins вы можете установить, сколько последних сборок вам необходимо сохранять, а также можете задать расписание, по которому будут осуществляться прогоны. Об этом вы найдете пару слов в разделе "Примечания". Помимо этого, в Jenkins есть еще много различных функций, которые можно изучить, и в дальнейшем успешно применять к вашим проектам. Однако на данном этапе будет достаточно того функционала, что был описан выше.
Авторизуйтесь в google‑аккаунте
Выберите "Управление аккаунт google"
Перейдите во вкладку "безопасность"
Включите двухфакторную аутентификацию (если не включена)
Перейдите в раздел "Пароли приложений" (можно через поисковую строку "Поиск в
аккаунте Google" - так даже удобнее и быстрее)
Создайте приложение, задав имя (например, Jenkins. Но на самом деле это не имеет никакого значения) После нажатия кнопки "создать" отобразится пароль. Скопируйте и вставьте его в SMTP_PASSWORD)
Почему лучше использовать пароль приложений вместо обычного пароля от почты:
• Безопасность: Если ваш код (или файл.env) будет скомпрометирован (например, попадет в публичный репозиторий GitHub), злоумышленник получит доступ к вашей почте и сможет делать с ней что угодно.
• Блокировка аккаунта: Многие почтовые сервисы (особенно Gmail) считают подозрительной отправку писем из автоматизированных скриптов с использованием обычного пароля и могут заблокировать ваш аккаунт.
• Нарушение условий использования: Некоторые почтовые сервисы прямо запрещают использование обычного пароля для автоматической отправки писем.
Я предпочитаю устанавливать ограничение на хранение количества сборок, как как, если их становится очень много, Jenkins начинает неистово тормозить при запуске сборки
Все прошедшие сборки отображены в разделе "builds", но можно в настройках вашего проекта указать, сколько последних сборок вы хотите сохранять: настройки проекта => общие настройки => удалять устаревшие сборки => "Сколько последних сборок хранить" - проставить нужное количество
Если вам нужна еще помощь, или вы хотите более наглядно увидеть процесс создания автотестов в Jenkins, то можете перейти на YouTube‑канал компании Коммит, где выложено подробное видео с пошаговой инструкцией по данной статье
https://youtu.be/kT8T80lTx8c [15]
Помимо данного видео, на этом канале вы найдете еще много полезной информации, опубликованной моими коллегами.
Вот и всё! Теперь в вашем арсенале есть мощная связка из Postman, Jenkins и Python, готовая к работе как на Windows, так и на macOS. Этот метод отлично масштабируется и легко адаптируется под специфику различных проектов. Надеюсь, статья оказалась полезной и поможет вам превратить рутинные проверки в изящный автоматизированный процесс. Помните: автоматизация - это не магия, а набор правильно настроенных инструментов. Пробуйте, экспериментируйте, и пусть ваши тесты всегда будут зелеными, а отчеты наглядными. Удачи в практике!
Автор: NikMar91
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/456733
Ссылки в тексте:
[1] сам скрипт и сопутствующие файлы.env: https://github.com/marussia199191-collab/For-Habr/tree/main
[2] Example_collection.postman_collection.json: https://github.com/marussia199191-collab/For-Habr/blob/main/Example_collection.postman_collection.json
[3] test.postman_environment.json: https://github.com/marussia199191-collab/For-Habr/blob/main/test.postman_environment.json
[4] code.py: https://github.com/marussia199191-collab/For-Habr/blob/main/code.py
[5] env.email: https://github.com/marussia199191-collab/For-Habr/blob/main/env.email
[6] env.paths: https://github.com/marussia199191-collab/For-Habr/blob/main/env.paths
[7] официальный сайт Node.js : https://nodejs.org/
[8] официального сайта: https://www.python.org/downloads/
[9] официального сайта Oracle: https://www.oracle.com/java/technologies/javase-jdk11-downloads.html
[10] https://github.com/allure‑framework/allure2/releases: https://github.com/allure-framework/allure2/releases
[11] allure-2.XX.X.zip: http://allure-2.XX.X.zip
[12] официальный сайт Jenkins.: https://www.jenkins.io/download/
[13] : http://localhost:8080/
[14] Visual studio code: https://code.visualstudio.com/download
[15] https://youtu.be/kT8T80lTx8c: https://youtu.be/kT8T80lTx8c
[16] Источник: https://habr.com/ru/articles/1071232/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1071232
Нажмите здесь для печати.