hw4: finalize selenoid and ansible workflow with citrus tests

This commit is contained in:
2026-02-27 01:38:06 +03:00
parent c06e9a89f1
commit 7ddea2e997
36 changed files with 1171 additions and 122 deletions

202
README.md
View File

@@ -1,97 +1,149 @@
# OTUS Selenium Homework 1
# OTUS Homework 4: Selenoid + GGR + Nginx
## Цель проекта
Автоматизировать 3 UI-сценария на `https://otus.ru` с использованием Selenium WebDriver 4+, JUnit 6, Guice DI, listeners, Stream API, Jsoup и обязательных проверок качества (Checkstyle + SpotBugs).
В этом проекте я собрал инфраструктуру для запуска UI-тестов через Selenoid и добавил Ansible-деплой для локального стенда и удаленных VM.
## Стек технологий
- Java 21
- Maven
- Selenium `4.40.0`
- WebDriverManager `6.3.3`
- JUnit `6.0.2`
- Guice `7.0.0`
- Jsoup `1.22.1`
- Guava `33.5.0-jre`
- SLF4J `2.0.17`
- Logback `1.5.31`
- Checkstyle
- SpotBugs
## Что реализовано
- UI-тесты из HW1 запускаются через удаленный `RemoteWebDriver` (Selenoid).
- Поддержаны браузеры: `chrome`, `firefox`, `mobile_chrome`.
- Подняты сервисы: `selenoid`, `selenoid-ui`, `ggr`, `nginx`.
- Один inventory для всех стендов: `localhost` (WSL), `vm1`, `vm2`.
## Реализованные сценарии
1. Поиск курса по имени.
- Открытие каталога `https://otus.ru/catalog/courses`
- Поиск курса по имени через Stream API
- Клик по плитке курса
- Проверка заголовка открытого курса
Точки доступа:
- UI: `http://<host_ip>/`
- WebDriver: `http://<host_ip>/wd/hub`
2. Самые ранние/поздние курсы по дате старта.
- Открытие каталога `https://otus.ru/catalog/courses`
- Поиск ранних и поздних курсов через Stream API + `reduce`
- При совпадении дат проверяются все курсы с этой датой
- Проверка названия и даты старта на странице курса через Jsoup
## Версии в проекте
Настройки лежат в `ansible/inventory/group_vars/all.yml`.
3. Случайная категория с главной страницы.
- Открытие `https://otus.ru`
- Открытие меню «Обучение»
- Выбор случайной категории
- Проверка, что открыта корректная категория
Браузеры:
- Chrome: `128.0`, `127.0`
- Firefox: `125.0`, `124.0`
## Архитектура
- 2-уровневый тест-дизайн: `tests` + `page objects`
- DI через Guice для тестов и страниц
- JUnit 6 Extension (`GuiceExtension`), без базового класса-теста
- Фабрика драйвера:
- `DriverFactory` (интерфейс)
- `ChromeDriverFactory` (реализация)
- `WebDriverProvider` (жизненный цикл драйвера + декоратор listener)
- Подсветка через listener:
- Подсветка ставится в `beforeClick`
- Снимается в `afterClick`
- Стиль элемента возвращается в исходное состояние
Образы инфраструктуры:
- `aerokube/selenoid:1.11.3`
- `aerokube/selenoid-ui:1.10.11`
- `aerokube/ggr:1.7.2`
- `aerokube/ggr-ui:latest-release`
- `nginx:1.28.2`
## Структура проекта
- `src/main/java/ru/kovbasa/config` — DI-конфигурация
- `src/main/java/ru/kovbasa/driver` — фабрика и провайдер WebDriver
- `src/main/java/ru/kovbasa/listeners` — listener подсветки
- `src/main/java/ru/kovbasa/pages` — Page Object классы
- `src/main/java/ru/kovbasa/elements` — типизированные UI-элементы
- `src/test/java/ru/kovbasa/config` — JUnit extension для DI
- `src/test/java/ru/kovbasa/tests` — автотесты
## Что нужно подготовить перед запуском
На каждой VM должен быть пользователь `ansible`:
- вход по SSH-ключу;
- `sudo` без пароля (`NOPASSWD`).
## Требования к окружению
1. Установлен JDK 21 (доступен в `PATH`)
2. Установлен Google Chrome
3. Установлен Maven 3.9+
4. Есть доступ в интернет и к `otus.ru` (тесты запускаются на живом сайте)
Ниже один простой вариант первичной подготовки VM.
## Запуск
### 1. Запуск только тестов
1. На локальной машине генерирую ключи (если их еще нет):
```bash
mvn test
ssh-keygen -f ~/.ssh/id_ed25519
```
### 2. Полная проверка (тесты + Checkstyle + SpotBugs)
2. Захожу на VM под `root`:
```bash
mvn verify
ssh root@10.10.2.127
```
### 3. Запуск отдельного тестового класса
3. Под `root` создаю пользователя `ansible`, добавляю в `sudo` и в `sudoers`:
```bash
mvn "-Dtest=ru.kovbasa.tests.CourseSearchTest" test
useradd -m -s /bin/bash ansible
usermod -aG sudo ansible
echo "ansible ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible
chmod 440 /etc/sudoers.d/ansible
```
## Параметры запуска
Пробрасываются через Maven Surefire:
- `base.url` (по умолчанию `https://otus.ru`)
- `course.name` (по умолчанию `Python Developer`)
Пример переопределения:
4. Под `root` кладу публичный ключ в профиль `ansible`:
```bash
mvn "-Dcourse.name=Python Developer" test
install -d -m 700 -o ansible -g ansible /home/ansible/.ssh
cat >> /home/ansible/.ssh/authorized_keys
```
После запуска этой команды вставляю содержимое `~/.ssh/id_ed25519.pub`, затем `Ctrl+D`.
5. Под `root` выставляю права:
```bash
chown ansible:ansible /home/ansible/.ssh/authorized_keys
chmod 600 /home/ansible/.ssh/authorized_keys
```
## Quality Gates
- Checkstyle и SpotBugs выполняется в фазе `verify`
6. Проверяю вход под `ansible`:
```bash
ssh -i ~/.ssh/id_ed25519 ansible@10.10.2.127 "whoami && sudo -n true && echo sudo_ok"
```
## Примечания
- Тесты зависят от текущей верстки/контента `otus.ru`.
## Как добавить новые VM
1. Добавляю хост в `ansible/inventory/hosts.ini`.
2. Создаю `ansible/inventory/host_vars/vmN.yml`:
```yaml
ansible_host: <ip>
ansible_user: ansible
ggr_selenoid_host_override: selenoid
```
## Запуск Ansible
В PowerShell синтаксис `VAR=value command` не работает, поэтому запускаю через `wsl bash -lc`.
Важно: `--limit` должен быть внутри кавычек команды.
### localhost (WSL)
```powershell
wsl bash -lc "cd /mnt/c/Users/spawn/IdeaProjects/otus-autotests/homework_1/ansible && ANSIBLE_ROLES_PATH=./roles ansible-playbook -i inventory/hosts.ini playbooks/site.yml --limit localhost"
```
### VM1
```powershell
wsl bash -lc "cd /mnt/c/Users/spawn/IdeaProjects/otus-autotests/homework_1/ansible && ANSIBLE_ROLES_PATH=./roles ansible-playbook -i inventory/hosts.ini playbooks/site.yml --limit vm1"
```
### VM2
```powershell
wsl bash -lc "cd /mnt/c/Users/spawn/IdeaProjects/otus-autotests/homework_1/ansible && ANSIBLE_ROLES_PATH=./roles ansible-playbook -i inventory/hosts.ini playbooks/site.yml --limit vm2"
```
Если ключ используется из `/mnt/c/...`, в WSL может быть ошибка `UNPROTECTED PRIVATE KEY FILE`.
Я использую копию ключа в WSL-профиле:
```bash
mkdir -p ~/.ssh
cp /mnt/c/Users/spawn/.ssh/id_ed25519 ~/.ssh/id_ed25519
cp /mnt/c/Users/spawn/.ssh/id_ed25519.pub ~/.ssh/id_ed25519.pub
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
```
## Команды для запуска тестов
### Все UI-тесты (Chrome)
```bash
mvn "-Dexecution.mode=selenoid" "-Dbrowser=chrome" "-Dbrowser.version=128.0" "-Dselenoid.url=http://10.10.2.112/wd/hub" test
```
### Конкретный UI-тест
```bash
mvn "-Dexecution.mode=selenoid" "-Dbrowser=chrome" "-Dbrowser.version=128.0" "-Dselenoid.url=http://10.10.2.112/wd/hub" "-Dtest=ru.kovbasa.tests.CourseSearchTest" test
```
### Mobile Chrome
```bash
mvn "-Dexecution.mode=selenoid" "-Dbrowser=mobile_chrome" "-Dbrowser.version=128.0" "-Dselenoid.url=http://10.10.2.112/wd/hub" test
```
### Firefox
```bash
mvn "-Dexecution.mode=selenoid" "-Dbrowser=firefox" "-Dbrowser.version=125.0" "-Dselenoid.url=http://10.10.2.112/wd/hub" test
```
### Citrus (HW3 API)
Citrus: вынесен в отдельный модуль `citrus-tests`, реализовано на базе HW3;
```bash
mvn -f citrus-tests/pom.xml test
```
### Запуск тестов через Ansible
```powershell
wsl bash -lc "cd /mnt/c/Users/spawn/IdeaProjects/otus-autotests/homework_1/ansible && ANSIBLE_ROLES_PATH=./roles ansible-playbook -i inventory/hosts.ini playbooks/site.yml --limit vm1 -e run_tests_via_ansible=true"
```
## Запуск с Linux/macOS
На Linux/macOS:
```bash
cd ansible
ANSIBLE_ROLES_PATH=./roles ansible-playbook -i inventory/hosts.ini playbooks/site.yml --limit vm1
```