Skip to content

Latest commit

 

History

History
373 lines (285 loc) · 24.7 KB

File metadata and controls

373 lines (285 loc) · 24.7 KB

Autotest Generator Project Map

Обзор проекта

Проект представляет собой инструмент для автоматической генерации автотестов на Python (Selenium + Allure) на основе записанных действий пользователя в браузере. Состоит из двух основных компонентов:

  1. Backend-сервер на Python FastAPI, который принимает данные о записанных шагах и генерирует готовый код тестов с поддержкой Page Object Model, условных блоков, Data-Driven Testing и интеграции с Allure.
  2. Расширение для Chrome (Manifest V3), которое инжектируется в веб-страницы, записывает действия пользователя (клики, ввод, наведение и т.д.), собирает информацию об элементах (локаторы, атрибуты) и отправляет данные на сервер для генерации кода.

Проект предназначен для ускорения написания UI-автотестов, особенно в средах с частыми изменениями вёрстки, благодаря использованию «лечащих» локаторов (healing locators) и автоматического скроллинга.


Архитектура

Backend (FastAPI)

Серверная часть построена на FastAPI с использованием SQLAlchemy (SQLite) для хранения лицензий и пользователей. Структура модулей:

  • app/main.py — точка входа, создаёт экземпляр FastAPI, настраивает CORS (разрешены все источники для разработки), подключает маршруты из endpoints.py.
  • app/database.py — конфигурация подключения к SQLite (test_generator.db), создание engine и сессий.
  • app/models.py — декларативные модели SQLAlchemy:
    • User (пользователи, email + хеш пароля)
    • License (лицензии с ключом, привязкой к пользователю, сроком действия и активностью).
  • app/schemas.py — Pydantic-схемы для валидации входящих/исходящих данных:
    • Step, GenerationRequest, GenerationResponse, TestCaseData.
  • app/crud.py — функции для работы с БД: получение лицензии по ключу, проверка её валидности.
  • app/dependencies.py — FastAPI-зависимости:
    • get_db — предоставляет сессию БД;
    • get_valid_license — извлекает ключ из заголовка Authorization: Bearer <key> и проверяет его.
  • app/code_generator.py — ядро логики генерации кода. Содержит:
    • Константу BASE_PAGE_PYTHON_CODE — готовый класс BasePage с методами для надёжных действий (клик, ввод, ожидание и т.д.) и healing-локаторами.
    • Функции _generate_element_name, _sanitize_for_function_name для формирования имён переменных и методов.
    • Асинхронную функцию generate_full_code_on_server, которая собирает финальный Python-код на основе переданных тест-кейсов и опций.
    • Логику построения Page Object Model (генерация класса страницы с локаторами и методами), генерации тестовых функций с декораторами Allure, добавления BasePage при необходимости.
  • app/api/v1/endpoints.py — маршруты API:
    • POST /api/v1/generate — основной эндпоинт генерации кода (требует валидной лицензии).
    • GET /api/v1/validate — проверка лицензии.
    • POST /api/v1/dev/create-user-and-license — dev-метод для создания пользователя и лицензии (используется для первоначальной настройки).
  • app/core/config.py — пустой файл (зарезервирован для конфигурации окружения).

Frontend (Chrome Extension)

Расширение работает по модели Manifest V3 и состоит из следующих частей:

  • client/manifest.json — декларация расширения:
    • permissions: storage, activeTab, scripting, contextMenus, offscreen, downloads, sidePanel.
    • host_permissions: http://localhost:11434/ (для Ollama) и <all_urls>.
    • background service worker: background.js.
    • side panel: popup.html (основной интерфейс).
    • content script: content_script.js (инжектируется во все страницы).
    • options page: options.html.
  • client/background.js — центральный управляющий скрипт:
    • Управление состоянием записи (флаги isRecording, isAssertMode, условные блоки).
    • Обработка сообщений от popup, content script и контекстного меню.
    • Сохранение состояния в chrome.storage.local (тест-кейсы, коллекции, окружения, переменные).
    • Отправка запроса на бекенд при генерации кода (с лицензионным ключом).
    • Работа с offscreen document для обрезки скриншотов.
  • client/content_script.js — скрипт, исполняемый в контексте страницы:
    • Отслеживает события click, input, change, dblclick, contextmenu.
    • Собирает детальную информацию об элементе (селекторы, атрибуты, координаты).
    • Реализует режим «добавления проверки» (assert mode) с изменённым курсором.
    • Подсвечивает элементы при наведении в списке шагов.
  • client/popup.js — логика side panel:
    • Отображает текущие шаги, коллекции, тест-кейсы, переменные окружения.
    • Управление записью (старт/стоп), добавление проверок, условных блоков.
    • Генерация кода с настройками (генерировать POM, тест, BasePage).
    • Drag-and-drop сортировка шагов (используется sortable.min.js).
  • client/options.js — страница настроек расширения:
    • Настройка LLM (Ollama URL, модель), кастомного data-атрибута для локаторов, стратегии локаторов, лицензионного ключа.
  • client/offscreen.js (не показан в списке файлов, но упоминается) — используется для обрезки скриншотов через canvas.
  • HTML/CSS файлы: popup.html, options.html, offscreen.html, popup.css.

Взаимодействие компонентов

  1. Пользователь открывает side panel расширения, вводит имя класса страницы, нажимает «Начать запись».
  2. Content script начинает фиксировать действия на активной вкладке, передаёт их в background, который сохраняет шаги в состоянии.
  3. После завершения записи пользователь настраивает опции генерации и нажимает «Сгенерировать код».
  4. Background формирует запрос к http://127.0.0.1:8000/api/v1/generate, включая все шаги, переменные окружения и настройки.
  5. Сервер проверяет лицензионный ключ, вызывает generate_full_code_on_server и возвращает сгенерированный Python-код.
  6. Расширение копирует код в буфер обмена (либо показывает ошибку).

Детали реализации

Модели данных (State)

Состояние расширения хранится в chrome.storage.local под ключом autotestProState. Структура:

{
  isRecording: boolean,
  isAssertMode: boolean,
  isRecordingIfCondition: boolean,
  isRecordingInConditionalBlock: boolean,
  conditionalRecordingContext: 'then' | 'else',
  environments: { dev: {}, prod: {} },
  activeEnvironment: string,
  collections: { [id]: { id, name } },
  testCases: {
    [id]: {
      id,
      name,
      collectionId,
      recordedSteps: Step[],
      pageClassName: string
    }
  },
  activeCollectionId: string,
  activeTestCaseId: string,
  // … другие служебные флаги
}

Каждый шаг (Step) содержит:

  • id, type, subType
  • data (информация об элементе)
  • locators (массив строк вида "(By.CSS_SELECTOR, '…')")
  • allureStep (читаемое название для Allure)
  • code (сгенерированные methodDefinition и methodCall)
  • variableName, variableForValue (для DDT)
  • screenshot (data URL обрезанного скриншота)

Генерация кода

Алгоритм generate_full_code_on_server:

  1. Сбор локаторов и методов POM: рекурсивный обход шагов всех тест-кейсов для данной страницы, формирование словаря уникальных локаторов и определений методов.
  2. Генерация класса Page Object (если options.generatePom):
    • Импорты (BasePage, By, allure).
    • Определение локаторов как атрибутов класса.
    • Добавление методов (каждый метод декорируется @allure.step).
  3. Генерация тестовой функции (если options.generateTest):
    • Формирование названия функции на основе имени тест-кейса (sanitize_for_function_name).
    • Декораторы @allure.feature (коллекция) и @allure.title (имя теста).
    • Создание экземпляра Page Object.
    • Добавление переменных окружения и DDT-переменных.
    • Рекурсивное построение вызовов методов (с учётом вложенных условных блоков).
  4. Добавление BasePage (если options.generateBasePage): в вывод включается готовый код класса BasePage с healing-методами и автоматическим скроллингом.

Итоговый код представляет собой concatenation этих частей.

Лицензирование

Лицензирование реализовано через модель «пользователь – лицензия». Для генерации кода требуется передать в заголовке Authorization: Bearer <license_key>. Сервер проверяет:

  • Наличие лицензии с таким ключом в БД.
  • Активность (is_active).
  • Срок действия (expires_at).

Dev-эндпоинт create-user-and-license создаёт пользователя с хешированным паролем (bcrypt) и лицензию со случайным UUID ключом, действующую 30 дней.

Работа с расширением

  • Контекстное меню: добавлены категории «Проверки», «Ожидания», «Действия» для ручного добавления шагов без использования side panel.
  • Режим проверки (assert mode): при активации курсор меняется на crosshair, клик по элементу записывает шаг проверки (например, assertVisible).
  • Условные блоки (IF/ELSE): позволяют записывать шаги внутри условия. Реализовано через флаги isRecordingIfCondition и isRecordingInConditionalBlock, а также рекурсивную структуру шагов.
  • Подсветка элементов: при наведении на шаг в списке соответствующий элемент на странице выделяется синим dashed outline.

Интеграция с LLM (Ollama)

Расширение поддерживает опциональное использование локального LLM (через Ollama) для:

  • Генерации человекочитаемых названий шагов Allure.
  • Предложения оптимальных CSS-селекторов на основе HTML-контекста.

Настройки LLM хранятся в chrome.storage.sync и настраиваются на странице options.


Зависимости

Python (backend)

Указаны в requirements.txt:

fastapi
uvicorn[standard]
sqlalchemy
pydantic
python-jose[cryptography]
passlib[bcrypt]
requests

Фактические версии не зафиксированы, но проект использует:

  • FastAPI ^0.104.0 (с поддержкой Pydantic v2)
  • SQLAlchemy ^2.0.0
  • python-jose для JWT (хотя в коде не используется, оставлено для возможного расширения)
  • passlib для хеширования паролей (bcrypt)
  • requests для возможных внешних вызовов (не используется в текущей реализации)

Неявные зависимости (нужны для сгенерированного кода, но не для работы сервера):

  • selenium (версии 4.x)
  • allure-pytest (или allure-python-commons)
  • pytest

Браузерное расширение

  • Manifest V3 — требует Chrome 88+.
  • Иконки — папка client/icons (не показана в списке файлов, но упоминается в manifest.json).
  • Сторонние библиотеки:
    • sortable.min.js (для drag-and-drop переупорядочивания шагов).

Опциональные

  • Ollama (локальный сервер LLM) — для улучшения генерации селекторов и названий шагов. По умолчанию ожидается на http://localhost:11434, модель llama3.

Конфигурация

Сервер

Конфигурация сервера задаётся в коде (app/database.py):

  • DATABASE_URL = "sqlite:///./test_generator.db" — SQLite файл в корне проекта.
  • CORS разрешены все источники (origins = ["*"]) — только для разработки.

Для production следует:

  1. Заменить DATABASE_URL на PostgreSQL/MySQL.
  2. Ограничить CORS конкретными доменами.
  3. Вынести настройки в переменные окружения (планируется через app/core/config.py).

Расширение

Настройки расширения хранятся в chrome.storage.sync (синхронизируются между устройствами) и доступны через страницу options.html:

  • useLlm (boolean) — использовать ли LLM.
  • ollamaUrl (string) — URL Ollama сервера.
  • llmModel (string) — модель (по умолчанию llama3).
  • customTestId (string) — кастомный data-атрибут для локаторов (по умолчанию data-testid).
  • locatorStrategy ('smart', 'css', 'xpath') — стратегия выбора локаторов.
  • excludeXpath (boolean) — исключать ли XPath из списка локаторов.
  • licenseKey (string) — лицензионный ключ для доступа к серверу.

Команды для запуска (локально)

1. Запуск backend-сервера

# Клонирование репозитория (предполагается, что проект уже склонирован)
cd autotest_generator

# Создание виртуального окружения (Windows, cmd)
python -m venv .venv
.venv\Scripts\activate

# Установка зависимостей
pip install -r requirements.txt

# Запуск сервера FastAPI на http://127.0.0.1:8000
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000

Примечание: Для PowerShell используйте .\.venv\Scripts\Activate.ps1.

2. Создание лицензии (опционально, но необходимо для работы)

После запуска сервера откройте новую терминальную сессию и выполните:

curl -X POST "http://127.0.0.1:8000/api/v1/dev/create-user-and-license?email=user@example.com"

В ответе будет JSON с полем license_key. Скопируйте этот ключ.

3. Установка расширения в Chrome

  1. Откройте Chrome и перейдите на страницу chrome://extensions/.
  2. Включите «Режим разработчика» (переключатель в правом верхнем углу).
  3. Нажмите «Загрузить распакованное расширение».
  4. Выберите папку autotest_generator/client.
  5. Расширение появится в списке; закрепите его на панели инструментов для удобства.

4. Настройка расширения

  1. Щёлкните по иконке расширения правой кнопкой → «Параметры» (или откройте chrome://extensions/, найдите Selenium CodeGen и нажмите «Details» → «Extension options»).
  2. В поле «Лицензионный ключ» вставьте ключ, полученный на шаге 2.
  3. При необходимости настройте LLM (если у вас запущен Ollama) или измените стратегию локаторов.
  4. Сохраните настройки.

5. Запись теста

  1. Откройте любую веб-страницу, которую хотите тестировать.
  2. Нажмите на иконку расширения — откроется side panel.
  3. Введите «Имя класса страницы» (например, LoginPage).
  4. Нажмите «▶️ Начать запись».
  5. Выполните на странице нужные действия (клики, ввод текста, выбор из выпадающего списка и т.д.).
  6. Для добавления проверок нажмите «🕵️ Добавить проверку» и кликните по элементу на странице.
  7. Для условных блоков используйте «❓ Добавить IF».
  8. По завершении нажмите «⏹️ Стоп».

6. Генерация кода

  1. В side panel убедитесь, что отмечены нужные опции:
    • ✅ Генерировать POM
    • ✅ Генерировать тест
    • ✅ Генерировать BasePage (рекомендуется)
  2. Нажмите «📋 Сгенерировать код».
  3. Если сервер запущен и лицензия валидна, код будет скопирован в буфер обмена.
  4. Вставьте код в файл .py в вашем тестовом проекте.

7. Запуск сгенерированного теста

Сгенерированный код требует установленных selenium, allure-pytest и драйвера браузера (например, ChromeDriver).

# Установка зависимостей для тестов
pip install selenium allure-pytest pytest

# Запуск теста (пример)
pytest your_generated_test.py --alluredir=./allure-results

Структура файлов

autotest_generator/
├── .gitignore
├── requirements.txt
├── test_generator.db                     # SQLite база (создаётся автоматически)
├── app/
│   ├── __init__.py
│   ├── main.py                           # Точка входа FastAPI
│   ├── database.py                       # Настройка SQLAlchemy
│   ├── models.py                         # Модели User, License
│   ├── schemas.py                        # Pydantic схемы
│   ├── crud.py                           # Функции работы с БД
│   ├── dependencies.py                   # FastAPI зависимости
│   ├── code_generator.py                 # Логика генерации кода (ядро)
│   ├── api/
│   │   ├── __init__.py
│   │   └── v1/
│   │       ├── __init__.py
│   │       └── endpoints.py              # Эндпоинты API
│   └── core/
│       └── __init__.py
│       └── config.py                     # Пусто (резерв под конфигурацию)
└── client/                               # Расширение Chrome
    ├── manifest.json
    ├── background.js                     # Service worker
    ├── content_script.js                 # Скрипт, инжектируемый в страницы
    ├── popup.js                          # Логика side panel
    ├── popup.html
    ├── popup.css
    ├── options.js                        # Настройки расширения
    ├── options.html
    ├── offscreen.js                      # Обрезка скриншотов
    ├── offscreen.html
    ├── sortable.min.js                   # Библиотека сортировки
    └── icons/                            (не показаны)

Примечания

  • Поддержка браузеров: Расширение разработано для Chrome, но должно работать в любом Chromium-браузере (Edge, Brave, Opera).
  • Безопасность: В текущей реализации CORS открыты для всех источников, а лицензионный ключ передаётся в заголовке без шифрования. Для production использования необходимо добавить HTTPS и JWT-токены.
  • Расширяемость: Код генератора построен модульно, что позволяет добавлять новые типы шагов (например, drag-and-drop) без изменения архитектуры.
  • Производительность: Генерация кода выполняется синхронно и может быть медленной при большом количестве шагов (сотни). Рекомендуется разбивать тест-кейсы на логические блоки.
  • Ограничения: Расширение не записывает действия внутри shadow DOM и не обрабатывает сложные SPA-навигации (например, переходы через History API). Требуется ручная доработка сгенерированного кода.