{"id":19411622,"url":"https://github.com/levvolkov/api-ci","last_synced_at":"2026-05-01T21:04:56.331Z","repository":{"id":228063073,"uuid":"772470931","full_name":"levvolkov/API-CI","owner":"levvolkov","description":"2.1 «Тестирование API, CI»  ","archived":false,"fork":false,"pushed_at":"2024-03-23T13:24:24.000Z","size":9755,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-07T15:21:35.219Z","etag":null,"topics":["appveyor","automated-testing","github-actions","gradle","testing-api","testing-ci"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/levvolkov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-15T08:59:12.000Z","updated_at":"2024-08-02T20:26:29.000Z","dependencies_parsed_at":"2024-03-23T14:40:34.737Z","dependency_job_id":null,"html_url":"https://github.com/levvolkov/API-CI","commit_stats":null,"previous_names":["levvolkov/api-ci"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levvolkov%2FAPI-CI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levvolkov%2FAPI-CI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levvolkov%2FAPI-CI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levvolkov%2FAPI-CI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/levvolkov","download_url":"https://codeload.github.com/levvolkov/API-CI/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240589044,"owners_count":19825289,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appveyor","automated-testing","github-actions","gradle","testing-api","testing-ci"],"created_at":"2024-11-10T12:22:23.484Z","updated_at":"2026-05-01T21:04:56.293Z","avatar_url":"https://github.com/levvolkov.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Java CI with Gradle](https://github.com/LevVolkov/API-CI/actions/workflows/gradle.yml/badge.svg)](https://github.com/LevVolkov/API-CI/actions/workflows/gradle.yml)\n[![Состояние сборки](https://ci.appveyor.com/api/projects/status/i2ql6nhfweloylk1?svg=true)](https://ci.appveyor.com/project/LevVolkov/api-ci)\n\n# 2.1 Домашнее задание к занятию «1.2. Тестирование API, CI» Задача 1-2.\n\nВ качестве результата пришлите ссылку на ваш GitHub-проект в личном кабинете студента на сайте [netology.ru](https://netology.ru).\n\nПервые две задачи этого занятия нужно делать в одном репозитории.\n\n**Важно**: если у вас что-то не получилось, то оформляйте issue [по установленным правилам](https://github.com/netology-code/aqa-homeworks/blob/master/report-requirements.md).\n\n**Важно**: не делайте ДЗ всех занятий в одном репозитории. Иначе вам потом придётся достаточно сложно подключать системы Continuous integration.\n\n## Как сдавать задачи\n\n1. Инициализируйте на своём компьютере пустой Git-репозиторий.\n1. Добавьте в него готовый файл [.gitignore](https://github.com/netology-code/aqa-homeworks/blob/master/.gitignore).\n1. Добавьте в этот же каталог код вашего приложения.\n1. Сделайте необходимые коммиты.\n1. Создайте публичный репозиторий на GitHub и свяжите свой локальный репозиторий с удалённым.\n1. Сделайте пуш — удостоверьтесь, что ваш код появился на GitHub.\n1. Ссылку на ваш проект отправьте в личном кабинете на сайте [netology.ru](https://netology.ru).\n1. Задачи, отмеченные, как необязательные, можно не сдавать, это не повлияет на получение зачёта.\n\nВ качестве примера можете посмотреть на этот [проект](https://github.com/netology-code-samples/aqa-ci-demo). Ваш по структуре должен выглядеть так же.\n\n## Информация по учебным JAR\n\nJAR файл учебного сервиса поместите в папку artifacts репозитория проекта. Для запуска учебного сервиса, находясь в папке проекта, выполните в терминале команду        \n```\njava -jar ./artifacts/app-mbank.jar\n```\n\nВажно: если вы работаете на Windows с турецкой локалью и при запуске учебных приложений получаете Exception вида:\n```\nCaused by: java.lang.NoSuchFieldException: wrıteHandlerReference (тут не английская i, а именно ı или ?)\n  at java.lang.Class.getDeclaredField(Unknown Source)\n  at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1.run(Unknown Source)\n  at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1.run(Unknown Source)\n  at java.security.AccessController.doPrivileged(Native Method)\n  ... 21 more\n```\n\nтогда вам все JAR нужно будет запускать командой:\n```\njava -Duser.language=en -Duser.country=US -jar ./artifacts/app-mbank.jar\n```\n\nЧасть `./artifacts/app-mbank.jar` может меняться в зависимости от имени файла учебного сервиса и папки с ним, но первая часть для вас во всех ДЗ при запуске на вашем ПК будет именно такой.\n\n## Задача №1: настройка CI\n\nНапоминаем, CI — это чаще всего отдельная система — сервер, набор серверов, облако — в которой ваш код и ваши автотесты собираются в автоматическом режиме без вашего непосредственного участия. Вы лишь настраиваете CI для того, чтобы при возникновении определённых событий, например, push в репозиторий, стартовал процесс сборки и прогона тестов.\n\nДетальнее про CI вы можете узнать, погуглив «Continuous integration», «Jenkins», «GitLab CI», «AppVeyor», «Travis», «CircleCI», «GitHub Actions».\n\nЧто надо сделать:   \n- клонировать [репозиторий с примерами учебного кода](https://github.com/netology-code/aqa-code/tree/master) во временную папку на локальный компьютер       \n- из папки api-ci локальной копии репозитория aqa-code копировать папку rest в папку с учебными проектами  \n- открыть папку rest в IDEA как проект Gradle, инициилизировать новый репозиторий в папке проекта rest   \n- создать в папке проекта папку artifacts, копировать в неё файл app-mbank.jar из папки api-ci       \n- настроить для проекта одну из CI на выбор: Github Actions ([инструкция](https://github.com/netology-code/aqa-homeworks/tree/master/github-actions-integration)) или Appveyor (см. инструкцию ниже)      \n- добавить файлы проекта в репозиторий, выполнить коммит и пуш   \n- удостовериться, что CI показывает, что в сборке выполняются все автотесты.            \n\n**Важно**: иногда можно настроить CI так, что там **всегда будет success** 😈! Не забывайте убедиться, что в CI сборка действительно падает, если вы запушите в GitHub падающий тест.\n\n\u003cdetails\u003e\n  \u003csummary\u003eПодсказка\u003c/summary\u003e\n  \n  Возможно, это как-то связано с файлом gradlew и правами доступа на него. Для добавления прав на запуск файла gradlew, добавьте в CI исполнение команды `chmod +x gradlew` перед тем как использовать этот файл как команду для работы с гредлом. \n\u003c/details\u003e\n\nОбщая схема работы выглядит следующим образом: CI должен запустить целевой сервис, который вы и тестируете, в фоновом режиме и ваши автотесты. Для этого мы будем на этот раз использовать возможности Bash.\n\nДля того чтобы запустить целевой сервис, есть несколько вариантов, самый простой из которых — положить JAR-файл прямо в ваш репозиторий. Когда AppVeyor будет выкачивать исходники автотестов, он выкачает и ваш сервис.\n\nКонечно, вы должны понимать, что в реальной жизни артефакты (собранный целевой сервис) хранятся в специальных системах, и процесс выкачивания будет зависеть от того, где и как хранится артефакт.\n\nВаш целевой сервис (SUT — System under test), расположен в файле [app-mbank.jar](app-mbank.jar), этот же файл используется в примерах на лекции. Вам нужно его положить в каталог `artifacts` вашего проекта, который необходимо создать.\n\nПоскольку файлы с расширением `.jar` находятся в списках `.gitignore`, вам нужно принудительно заставить Git следить за ними: `git add -f artifacts/app-mbank.jar`.\n\nПосле чего сделать `git push`. Обязательно удостоверьтесь, что файл попал в репозиторий.\n\n### AppVeyor\n\n[AppVeyor](https://www.appveyor.com) — одна из платформ, предоставляющих функциональность Continuous integration. В базовом варианте она бесплатна.\n\n#### Шаг 0. Конфигурация как код\n\nПоскольку вручную настраивать каждый проект в системе Continuous integration — лишняя трата времени, мы будем хранить всю конфигурацию для AppVeyor в специальном файле с названием `.appveyor.yml`.\n\nВажно: внимательно посмотрите на структуру деморепозитория из ваших лекций. Большинство инструментов используют подход «Configuration by exception», то есть конфигурируется только то, что не соответствует настройкам по умолчанию. Поэтому у вас всего два пути: либо использовать настройки по умолчанию и писать как можно меньше конфигурации, либо идти против системы и писать много конфигурации, а потом ещё и отлаживать её.\n\nФайл этот должен храниться в самом репозитории на GitHub, тогда AppVeyor будет автоматически подхватывать настройки из него:\n\n![](https://i.imgur.com/Gg7B961.png)\n\nYaml — формат данных, используемый многими системами для хранения конфигурации.\n\nСсылки:\n* [Wikipedia](https://en.wikipedia.org/wiki/YAML),\n* [спецификация](https://yaml.org/spec/1.2/spec.html).\n\nСтранички на Wikipedia достаточно для понимания базовых конструкций языка.\n\nAppVeyor предлагает вам два вида серверов, на которых можно проводить сборку вашего приложения: под управлением Windows или под управлением Linux. Можно организовать сборку под несколькими сразу, но для упрощения мы пока остановимся только на одной ОС для каждого вашего проекта.\n\n##### Linux Config\n\n```yaml\nimage: Ubuntu2004  # образ для сборки\n\nstack: jdk 11  # версия JDK\n\nbranches:\n  only:\n    - master  # ветка git\n\nbuild: off  # будем использовать свой скрипт сборки\n\ninstall:\n  # запускаем SUT (\u0026 означает, что в фоновом режиме не блокируем терминал для запуска тестов)\n  - java -jar ./artifacts/app-mbank.jar \u0026\n  - chmod +x gradlew\n\nbuild_script:\n  - ./gradlew test --info  # запускаем тест, флаг --info позволяет выводить больше информации\n```\n\nЕстественно, у вас должен возникнуть вопрос, а что будет, если SUT не успеет стартовать к моменту запуска автотестов?\n\nТогда ваши тесты упадут. Что с этим делать и как классифицировать подобные случаи, мы поговорим на следующих лекциях.\n\nНапоминаем, ваш `build.gradle` должен выглядеть вот так:\n```groovy\nplugins {\n    id 'java'\n}\n\ngroup 'ru.netology'\nversion '1.0-SNAPSHOT'\n\nsourceCompatibility = 11\ncompileJava.options.encoding = 'UTF-8'\ncompileTestJava.options.encoding = 'UTF-8'\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    testImplementation 'io.rest-assured:rest-assured:5.3.1'\n    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.1'\n    testImplementation 'io.rest-assured:json-schema-validator:4.3.1'\n}\n\ntest {\n    useJUnitPlatform()\n}\n```\n\n#### Шаг 1. Регистрация\n\n![](https://i.imgur.com/Rugmz7D.png)\n\n#### Шаг 2. Регистрация через GitHub\n\nAppVeyor предоставляет бесплатный тарифный план для публичных репозиториев GitHub, авторизация — также через GitHub:\n\n![](https://i.imgur.com/jXvftMb.png)\n\n#### Шаг 3. Разрешение доступа\n\nПри подключении необходимо разрешить AppVeyor получать уведомления:\n\n![](https://i.imgur.com/2Fvcj96.png)\n\n#### Шаг 4. Создание проекта\n\nПосле авторизации станет доступной панель управления, где можно создать новый проект:\n\n![](https://i.imgur.com/wUBKbYY.png)\n\nАвторизуйте AppVeyor в качестве OAuth App:\n\n![](https://i.imgur.com/oQadLLj.png)\n\nЭто даст возможность приложению получать уведомления о ваших `push` в репозиторий, модификации и т. д.\n\n![](https://i.imgur.com/2jwH6Sa.png)\n\nДетальнее об OAuth вы можете прочитать на:\n* https://oauth.net/2/,\n* https://auth0.com/docs/protocols/oauth2.\n\n#### Шаг 5. Выбор репозитория\n\nПосле авторизации достаточно будет нажать кнопку `ADD` напротив необходимого репозитория:\n\n![](https://i.imgur.com/4VQME6j.png)\n\nПосле настройки всего процесса каждый `push` в ветку `master` GitHub-репозитория будет приводить к запуску сборки на AppVeyor.\n\n#### Шаг 6. Status badge\n\nНа странице `Settings` — `Badges` AppVeyor предлагает код для бейджика статуса вашего проекта:\n\n![](https://i.imgur.com/DECtZjg.png)\n\nЭтот badge необходимо разместить в файле `README.md` для отображения текущего статуса вашего проекта:\n\n![](https://i.imgur.com/V9cOeJO.png)\n\n**Важно: убедитесь, что вы не скопировали бейджик с другого проекта. За такую хитрость ДЗ будет отправляться на доработку.**\n\n## Задача №2: JSON Schema\n\nJSON Schema предлагает нам инструмент валидации JSON-документов. С описанием вы можете познакомиться по [адресу](https://json-schema.org/understanding-json-schema).\n\nКак строится схема: \n```js\n{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\", // версия схемы: https://json-schema.org/understanding-json-schema/reference/schema.html\n  \"type\": \"array\", // тип корневого элемента: https://json-schema.org/understanding-json-schema/reference/type.html\n  \"items\": { // какие элементы допустимы внутри массива: https://json-schema.org/understanding-json-schema/reference/array.html#items\n    \"type\": \"object\", // должны быть объектами: https://json-schema.org/understanding-json-schema/reference/object.html\n    \"required\": [ // должны содержать следующие поля: https://json-schema.org/understanding-json-schema/reference/object.html#required-properties\n      \"id\",\n      \"name\",\n      \"number\",\n      \"balance\",\n      \"currency\"\n    ],\n    \"additionalProperties\": false, // дополнительных полей быть не должно \n    \"properties\": { // описание полей: https://json-schema.org/understanding-json-schema/reference/object.html#properties\n      \"id\": {\n        \"type\": \"integer\" // целое число: https://json-schema.org/understanding-json-schema/reference/numeric.html#integer\n      },\n      \"name\": {\n        \"type\": \"string\", // строка: https://json-schema.org/understanding-json-schema/reference/string.html\n        \"minLength\": 1 // минимальная длина — 1: https://json-schema.org/understanding-json-schema/reference/string.html#length\n      },\n      \"number\": {\n        \"type\": \"string\", // строка: https://json-schema.org/understanding-json-schema/reference/string.html\n        \"pattern\": \"^•• \\\\d{4}$\" // соответствует регулярному выражению: https://json-schema.org/understanding-json-schema/reference/string.html#regular-expressions\n      },\n      \"balance\": {\n        \"type\": \"integer\" // целое число: https://json-schema.org/understanding-json-schema/reference/numeric.html#integer\n      },\n      \"currency\": {\n        \"type\": \"string\" // строка: https://json-schema.org/understanding-json-schema/reference/string.html\n      }\n    }\n  }\n}\n```\n\nНачнем с изучения проекта, проверим необходимые условия для его реализации.   \n\nЧто нужно сделать:    \n\n#### Шаг 1. Зависимости проекта\n\n```groovy\ndependencies {\n    testImplementation 'io.rest-assured:rest-assured:5.3.1'\n    testImplementation 'io.rest-assured:json-schema-validator:4.3.1'\n    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'\n}\n```\n\n#### Шаг 2. JSON схема    \n\nВ каталоге `resources` в `src/test` и должен лежать файл схемы.    \n\n![](https://github.com/netology-code/aqa-homeworks/blob/master/api-ci/pic/schema.png)\n\n#### Шаг 3. Проверка ответа сервиса на соответсвие схеме    \n\nОдин из классов проекта должен содержать операцию проверки соответствия ответа схеме. \n\n```java\n      // код теста\n      .then()\n          .statusCode(200)\n          .body(matchesJsonSchemaInClasspath(\"accounts.schema.json\"));\n```\n\nВ тестовом классе должен быть импорт статического метода        \n\n```java\nimport static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;\n```\n\nУдостоверьтесь, что тесты проходят при соответствии ответа схеме и падают, если вы поменяете что-то в схеме, например, тип для `id`.\n\n#### Шаг 4. Доработать схему\n\nИзучите документацию на тип [`object`](https://json-schema.org/understanding-json-schema/reference/object.html) и найдите способ валидации значения поля на два из возможных значений: «RUB» или «USD».\n\nДоработайте схему соответствующим образом, удостоверьтесь, что тесты проходят, в том числе в CI.\n\nПоменяйте «RUB» на «RUR» в схеме и удостоверьтесь, что тесты падают, в том числе в CI.\n\nПришлите на проверку ссылку на ваш репозиторий. Удостоверьтесь, что в истории сборки были как success, так и fail, иначе будет не видно, как вы проверяли, что сборка падает в CI.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flevvolkov%2Fapi-ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flevvolkov%2Fapi-ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flevvolkov%2Fapi-ci/lists"}