Skip to content

levvolkov/API-CI

Repository files navigation

Java CI with Gradle Состояние сборки

2.1 Домашнее задание к занятию «1.2. Тестирование API, CI» Задача 1-2.

В качестве результата пришлите ссылку на ваш GitHub-проект в личном кабинете студента на сайте netology.ru.

Первые две задачи этого занятия нужно делать в одном репозитории.

Важно: если у вас что-то не получилось, то оформляйте issue по установленным правилам.

Важно: не делайте ДЗ всех занятий в одном репозитории. Иначе вам потом придётся достаточно сложно подключать системы Continuous integration.

Как сдавать задачи

  1. Инициализируйте на своём компьютере пустой Git-репозиторий.
  2. Добавьте в него готовый файл .gitignore.
  3. Добавьте в этот же каталог код вашего приложения.
  4. Сделайте необходимые коммиты.
  5. Создайте публичный репозиторий на GitHub и свяжите свой локальный репозиторий с удалённым.
  6. Сделайте пуш — удостоверьтесь, что ваш код появился на GitHub.
  7. Ссылку на ваш проект отправьте в личном кабинете на сайте netology.ru.
  8. Задачи, отмеченные, как необязательные, можно не сдавать, это не повлияет на получение зачёта.

В качестве примера можете посмотреть на этот проект. Ваш по структуре должен выглядеть так же.

Информация по учебным JAR

JAR файл учебного сервиса поместите в папку artifacts репозитория проекта. Для запуска учебного сервиса, находясь в папке проекта, выполните в терминале команду

java -jar ./artifacts/app-mbank.jar

Важно: если вы работаете на Windows с турецкой локалью и при запуске учебных приложений получаете Exception вида:

Caused by: java.lang.NoSuchFieldException: wrıteHandlerReference (тут не английская i, а именно ı или ?)
  at java.lang.Class.getDeclaredField(Unknown Source)
  at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1.run(Unknown Source)
  at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  ... 21 more

тогда вам все JAR нужно будет запускать командой:

java -Duser.language=en -Duser.country=US -jar ./artifacts/app-mbank.jar

Часть ./artifacts/app-mbank.jar может меняться в зависимости от имени файла учебного сервиса и папки с ним, но первая часть для вас во всех ДЗ при запуске на вашем ПК будет именно такой.

Задача №1: настройка CI

Напоминаем, CI — это чаще всего отдельная система — сервер, набор серверов, облако — в которой ваш код и ваши автотесты собираются в автоматическом режиме без вашего непосредственного участия. Вы лишь настраиваете CI для того, чтобы при возникновении определённых событий, например, push в репозиторий, стартовал процесс сборки и прогона тестов.

Детальнее про CI вы можете узнать, погуглив «Continuous integration», «Jenkins», «GitLab CI», «AppVeyor», «Travis», «CircleCI», «GitHub Actions».

Что надо сделать:

  • клонировать репозиторий с примерами учебного кода во временную папку на локальный компьютер
  • из папки api-ci локальной копии репозитория aqa-code копировать папку rest в папку с учебными проектами
  • открыть папку rest в IDEA как проект Gradle, инициилизировать новый репозиторий в папке проекта rest
  • создать в папке проекта папку artifacts, копировать в неё файл app-mbank.jar из папки api-ci
  • настроить для проекта одну из CI на выбор: Github Actions (инструкция) или Appveyor (см. инструкцию ниже)
  • добавить файлы проекта в репозиторий, выполнить коммит и пуш
  • удостовериться, что CI показывает, что в сборке выполняются все автотесты.

Важно: иногда можно настроить CI так, что там всегда будет success 😈! Не забывайте убедиться, что в CI сборка действительно падает, если вы запушите в GitHub падающий тест.

Подсказка

Возможно, это как-то связано с файлом gradlew и правами доступа на него. Для добавления прав на запуск файла gradlew, добавьте в CI исполнение команды chmod +x gradlew перед тем как использовать этот файл как команду для работы с гредлом.

Общая схема работы выглядит следующим образом: CI должен запустить целевой сервис, который вы и тестируете, в фоновом режиме и ваши автотесты. Для этого мы будем на этот раз использовать возможности Bash.

Для того чтобы запустить целевой сервис, есть несколько вариантов, самый простой из которых — положить JAR-файл прямо в ваш репозиторий. Когда AppVeyor будет выкачивать исходники автотестов, он выкачает и ваш сервис.

Конечно, вы должны понимать, что в реальной жизни артефакты (собранный целевой сервис) хранятся в специальных системах, и процесс выкачивания будет зависеть от того, где и как хранится артефакт.

Ваш целевой сервис (SUT — System under test), расположен в файле app-mbank.jar, этот же файл используется в примерах на лекции. Вам нужно его положить в каталог artifacts вашего проекта, который необходимо создать.

Поскольку файлы с расширением .jar находятся в списках .gitignore, вам нужно принудительно заставить Git следить за ними: git add -f artifacts/app-mbank.jar.

После чего сделать git push. Обязательно удостоверьтесь, что файл попал в репозиторий.

AppVeyor

AppVeyor — одна из платформ, предоставляющих функциональность Continuous integration. В базовом варианте она бесплатна.

Шаг 0. Конфигурация как код

Поскольку вручную настраивать каждый проект в системе Continuous integration — лишняя трата времени, мы будем хранить всю конфигурацию для AppVeyor в специальном файле с названием .appveyor.yml.

Важно: внимательно посмотрите на структуру деморепозитория из ваших лекций. Большинство инструментов используют подход «Configuration by exception», то есть конфигурируется только то, что не соответствует настройкам по умолчанию. Поэтому у вас всего два пути: либо использовать настройки по умолчанию и писать как можно меньше конфигурации, либо идти против системы и писать много конфигурации, а потом ещё и отлаживать её.

Файл этот должен храниться в самом репозитории на GitHub, тогда AppVeyor будет автоматически подхватывать настройки из него:

Yaml — формат данных, используемый многими системами для хранения конфигурации.

Ссылки:

Странички на Wikipedia достаточно для понимания базовых конструкций языка.

AppVeyor предлагает вам два вида серверов, на которых можно проводить сборку вашего приложения: под управлением Windows или под управлением Linux. Можно организовать сборку под несколькими сразу, но для упрощения мы пока остановимся только на одной ОС для каждого вашего проекта.

Linux Config
image: Ubuntu2004  # образ для сборки

stack: jdk 11  # версия JDK

branches:
  only:
    - master  # ветка git

build: off  # будем использовать свой скрипт сборки

install:
  # запускаем SUT (& означает, что в фоновом режиме не блокируем терминал для запуска тестов)
  - java -jar ./artifacts/app-mbank.jar &
  - chmod +x gradlew

build_script:
  - ./gradlew test --info  # запускаем тест, флаг --info позволяет выводить больше информации

Естественно, у вас должен возникнуть вопрос, а что будет, если SUT не успеет стартовать к моменту запуска автотестов?

Тогда ваши тесты упадут. Что с этим делать и как классифицировать подобные случаи, мы поговорим на следующих лекциях.

Напоминаем, ваш build.gradle должен выглядеть вот так:

plugins {
    id 'java'
}

group 'ru.netology'
version '1.0-SNAPSHOT'

sourceCompatibility = 11
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'io.rest-assured:rest-assured:5.3.1'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.1'
    testImplementation 'io.rest-assured:json-schema-validator:4.3.1'
}

test {
    useJUnitPlatform()
}

Шаг 1. Регистрация

Шаг 2. Регистрация через GitHub

AppVeyor предоставляет бесплатный тарифный план для публичных репозиториев GitHub, авторизация — также через GitHub:

Шаг 3. Разрешение доступа

При подключении необходимо разрешить AppVeyor получать уведомления:

Шаг 4. Создание проекта

После авторизации станет доступной панель управления, где можно создать новый проект:

Авторизуйте AppVeyor в качестве OAuth App:

Это даст возможность приложению получать уведомления о ваших push в репозиторий, модификации и т. д.

Детальнее об OAuth вы можете прочитать на:

Шаг 5. Выбор репозитория

После авторизации достаточно будет нажать кнопку ADD напротив необходимого репозитория:

После настройки всего процесса каждый push в ветку master GitHub-репозитория будет приводить к запуску сборки на AppVeyor.

Шаг 6. Status badge

На странице SettingsBadges AppVeyor предлагает код для бейджика статуса вашего проекта:

Этот badge необходимо разместить в файле README.md для отображения текущего статуса вашего проекта:

Важно: убедитесь, что вы не скопировали бейджик с другого проекта. За такую хитрость ДЗ будет отправляться на доработку.

Задача №2: JSON Schema

JSON Schema предлагает нам инструмент валидации JSON-документов. С описанием вы можете познакомиться по адресу.

Как строится схема:

{
  "$schema": "http://json-schema.org/draft-07/schema", // версия схемы: https://json-schema.org/understanding-json-schema/reference/schema.html
  "type": "array", // тип корневого элемента: https://json-schema.org/understanding-json-schema/reference/type.html
  "items": { // какие элементы допустимы внутри массива: https://json-schema.org/understanding-json-schema/reference/array.html#items
    "type": "object", // должны быть объектами: https://json-schema.org/understanding-json-schema/reference/object.html
    "required": [ // должны содержать следующие поля: https://json-schema.org/understanding-json-schema/reference/object.html#required-properties
      "id",
      "name",
      "number",
      "balance",
      "currency"
    ],
    "additionalProperties": false, // дополнительных полей быть не должно 
    "properties": { // описание полей: https://json-schema.org/understanding-json-schema/reference/object.html#properties
      "id": {
        "type": "integer" // целое число: https://json-schema.org/understanding-json-schema/reference/numeric.html#integer
      },
      "name": {
        "type": "string", // строка: https://json-schema.org/understanding-json-schema/reference/string.html
        "minLength": 1 // минимальная длина — 1: https://json-schema.org/understanding-json-schema/reference/string.html#length
      },
      "number": {
        "type": "string", // строка: https://json-schema.org/understanding-json-schema/reference/string.html
        "pattern": "^•• \\d{4}$" // соответствует регулярному выражению: https://json-schema.org/understanding-json-schema/reference/string.html#regular-expressions
      },
      "balance": {
        "type": "integer" // целое число: https://json-schema.org/understanding-json-schema/reference/numeric.html#integer
      },
      "currency": {
        "type": "string" // строка: https://json-schema.org/understanding-json-schema/reference/string.html
      }
    }
  }
}

Начнем с изучения проекта, проверим необходимые условия для его реализации.

Что нужно сделать:

Шаг 1. Зависимости проекта

dependencies {
    testImplementation 'io.rest-assured:rest-assured:5.3.1'
    testImplementation 'io.rest-assured:json-schema-validator:4.3.1'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'
}

Шаг 2. JSON схема

В каталоге resources в src/test и должен лежать файл схемы.

Шаг 3. Проверка ответа сервиса на соответсвие схеме

Один из классов проекта должен содержать операцию проверки соответствия ответа схеме.

      // код теста
      .then()
          .statusCode(200)
          .body(matchesJsonSchemaInClasspath("accounts.schema.json"));

В тестовом классе должен быть импорт статического метода

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;

Удостоверьтесь, что тесты проходят при соответствии ответа схеме и падают, если вы поменяете что-то в схеме, например, тип для id.

Шаг 4. Доработать схему

Изучите документацию на тип object и найдите способ валидации значения поля на два из возможных значений: «RUB» или «USD».

Доработайте схему соответствующим образом, удостоверьтесь, что тесты проходят, в том числе в CI.

Поменяйте «RUB» на «RUR» в схеме и удостоверьтесь, что тесты падают, в том числе в CI.

Пришлите на проверку ссылку на ваш репозиторий. Удостоверьтесь, что в истории сборки были как success, так и fail, иначе будет не видно, как вы проверяли, что сборка падает в CI.