Как всё начиналось

Когда мы начали разработку системы автотестирования для САПР-приложения, наша главная цель была переосмыслить процесс тестирования программ для 3D-моделирования. Нужно было ускорить тесты и сделать их надёжнее, минимизируя ручной труд.

Выбор Python как основного инструмента был однозначным, благодаря его простоте и мощи. Включение в проект PyAutoGUI стало ключевым моментом: это позволило нам точно имитировать действия пользователя, автоматизируя взаимодействие с интерфейсом на новом уровне.

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

Три кита системы

Разработка системы автотестирования подчёркивала важность модульной архитектуры. Мы разделили всё на три основных блока, каждый со своей зоной ответственности.

Инструмент записи действий

Первым делом нам нужно было решить вопрос - как захватывать и анализировать действия пользователя. Создали специализированный инструмент на основе формата JSON. Почему JSON? Он универсален, читается людьми и удобен для организации данных.

Этот инструмент оказался способным точно фиксировать широкий спектр пользовательских взаимодействий - от простых кликов до комплексных операций вроде перемещения объектов и выполнения комбинаций клавиш.

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

Особенность инструмента - его гибкость в управлении процессом записи. Пользователи могут в любой момент начать, приостановить или завершить запись. Это позволяет создавать точные пользовательские сценарии для тестирования.

Мы осознали важность удобного интерфейса для взаимодействия с инструментом. Для создания графического интерфейса пользователя выбрали стандартную библиотеку Python для GUI. Это позволило нам разработать интуитивно понятные диалоговые окна, через которые пользователи могут управлять процессом записи, настраивать параметры и выбирать место для сохранения итоговых данных.

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

Пример структуры записанного сценария

Записанный сценарий хранится в формате JSON и имеет следующую обобщённую структуру:

{
    "test_id": "TC_001",
    "test_name": "Создание элемента",
    "validation": {
        "method": "visual_compare",
        "expected_image": "screenshot_ref.png",
        "threshold": 0.95
    },
    "steps": [
        {
            "type": "mouse_click",
            "button": "left",
            "coords": {"x": 100, "y": 200}
        },
        {
            "type": "key_input",
            "keys": ["ctrl", "n"]
        },
        {
            "type": "text_entry",
            "value": "test_data"
        },
        {
            "type": "delay",
            "duration": 2.0
        }
    ]
}

Каждый шаг описывается как отдельный объект со своими параметрами, что позволяет гибко настраивать последовательность действий.

Упрощённая логика рекордера

Рекордер работает по следующему принципу:

class UserActionCapture:
    def __init__(self):
        self.is_active = False
        self.event_queue = []
        self.test_metadata = {}
    
    def capture_mouse(self, event):
        if not self.is_active:
            return
            
        step = {
            "type": "mouse_click" if event.pressed else "mouse_release",
            "button": event.button,
            "coords": {"x": event.x, "y": event.y},
            "timestamp": get_current_time()
        }
        self.event_queue.append(step)
    
    def capture_keyboard(self, event):
        if not self.is_active:
            return
            
        step = {
            "type": "key_input",
            "keys": [event.key],
            "timestamp": get_current_time()
        }
        self.event_queue.append(step)
    
    def export_scenario(self, filepath):
        scenario = {
            "test_id": generate_test_id(),
            "test_name": self.test_metadata.get("name", "Unnamed"),
            "steps": self.event_queue
        }
        save_json(scenario, filepath)

Этот подход позволяет захватывать все пользовательские действия в структурированном виде и воспроизводить их позже.

Система доставки и развёртывания

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

Мы автоматизировали процесс обновления ПО с помощью скриптов, которые подключаются к FTP-серверу для скачивания последних версий программ. Скрипты используют учетные данные для доступа к серверу, сравнивают версии программ на сервере и у нас локально. Если на сервере версия новее, скрипт автоматически загружает и устанавливает её, обеспечивая актуальность ПО без ручных операций.

Эти скрипты автоматически подключаются к серверу, проверяют наличие более новой версии файла. Если обнаруживается обновление, скрипт загружает и обновляет файлы, гарантируя, что мы всегда работаем с последней версией ПО. Это значительно упрощает процесс поддержания актуальности программного обеспечения, исключая необходимость ручного поиска и загрузки обновлений.

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

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

Процесс настройки и управления виртуальной машиной реализован через PowerShell, поскольку прямой запуск иногда приводил к нестабильной работе ВМ. Использование PowerShell позволяет более надёжно конфигурировать необходимые параметры виртуальной машины - объем памяти, количество ядер процессора, а также управлять копированием виртуального диска с необходимыми данными и приложениями. После копирования важно проверить целостность данных для безошибочного запуска.

Запуск машины в режиме headless через PowerShell особенно важен для автоматизации тестирования и развертывания, поскольку он позволяет операциям выполняться в фоне без необходимости визуального контроля со стороны пользователя.

Упрощённая логика управления виртуальными машинами

Скрипты автоматизации работают по следующему принципу:

# Конфигурация окружения
$vmConfig = @{
    Name = "CAD_Test_VM"
    DiskImage = "C:\VMs\test_base.vdi"
    Memory = "4GB"
    Processors = 2
    NetworkAdapter = "NAT"
}

# Клонирование базового образа
Clone-VMDisk -Source $vmConfig.DiskImage -Destination "C:\VMs\temp\test_run.vdi"

# Применение параметров виртуальной машины
Set-VMConfiguration -Name $vmConfig.Name -Config $vmConfig

# Запуск виртуальной машины
Start-VM -Name $vmConfig.Name -Mode Headless

# Ожидание инициализации
Wait-VMReady -Name $vmConfig.Name -Timeout 60

# Передача тестовых данных в ВМ
Copy-ToVM -VMName $vmConfig.Name -Source ".\tests\" -Destination "C:\Tests\"

# Запуск тестирования внутри ВМ
Invoke-VMCommand -VMName $vmConfig.Name -Script "C:\Tests\run_tests.ps1"

# Сбор результатов
Copy-FromVM -VMName $vmConfig.Name -Source "C:\Tests\results\" -Destination ".\results\"

# Остановка и очистка
Stop-VM -Name $vmConfig.Name -Force
Remove-VMDisk -Path "C:\VMs\temp\test_run.vdi"

Для обновления ПО используется отдельный скрипт:

class SoftwareUpdateManager:
    def __init__(self, remote_config):
        self.remote_url = remote_config["url"]
        self.auth_token = remote_config["token"]
        self.local_storage = "/path/to/builds"
    
    def sync_latest_build(self):
        # Подключение к удалённому хранилищу
        remote = connect_to_repository(self.remote_url, self.auth_token)
        
        # Сравнение версий
        available_version = remote.get_latest_version()
        current_version = self.get_installed_version()
        
        if available_version > current_version:
            # Загрузка новой сборки
            build_package = remote.download_build(available_version)
            local_path = os.path.join(self.local_storage, build_package.name)
            
            # Проверка целостности и установка
            if self.verify_package_integrity(build_package):
                self.deploy_build(local_path)
                return True
        
        return False

Эта связка PowerShell и Python скриптов обеспечивает полностью автоматизированный процесс подготовки, развёртывания и обновления тестового окружения.

Движок выполнения тестов

Основной компонент системы - приложение автотестирования, работающее непосредственно внутри виртуальных машин. Оно управляет установкой сборок ПО, запускает приложения и проводит автотесты, используя заранее подготовленные сценарии.

Центральное приложение системы автотестирования было разработано для управления всем циклом тестирования. Оно объединяет различные инструменты и методики, начиная от подготовки тестового окружения. Эта подготовка включает автоматическую установку свежих сборок программного обеспечения в новые виртуальные машины, гарантируя чистое начало для каждого теста.

Одним из решающих факторов в обеспечении точности тестирования стало использование референсных скриншотов, созданных в процессе записи действий пользователя. Эти скриншоты служат эталоном, с которым система с��авнивает изображения во время тестов, автоматически выявляя отклонения от ожидаемого поведения приложения. Такой подход позволяет не только фиксировать визуальные и функциональные сбои, но и детально анализировать поведение ПО в различных сценариях использования.

Одной из особенностей работы приложения стало применение сценариев в формате JSON, созданных с помощью инструмента для записи действий пользователя. Это даёт возможность точно воспроизводить различные действия в тестируемом ПО, включая сложные пользовательские операции.

Для имитации действий пользователя система опирается на инструменты автоматизации интерфейса, что позволяет с высокой точностью воспроизводить взаимодействие с программой. Это критически важно для обеспечения достоверности тестов и оценки поведения ПО в условиях, максимально приближенных к реальным.

Упрощённая логика парсера и исполнителя

Движок тестирования загружает JSON-сценарий и последовательно выполняет действия:

class ScenarioPlayer:
    def __init__(self, scenario_file):
        self.scenario = load_scenario(scenario_file)
        self.state = "ready"
        self.current_step = 0
    
    def execute_scenario(self):
        for step in self.scenario["steps"]:
            if self.state == "stopped":
                break
            
            # Обработка различных типов действий
            step_type = step.get("type")
            
            if step_type == "mouse_click":
                coords = step["coords"]
                button = step["button"]
                self.automation.click(coords["x"], coords["y"], button)
            
            elif step_type == "key_input":
                keys = step["keys"]
                self.automation.press_keys(keys)
            
            elif step_type == "text_entry":
                text = step["value"]
                self.automation.type_text(text)
            
            elif step_type == "delay":
                duration = step["duration"]
                time.sleep(duration)
            
            self.current_step += 1
            time.sleep(0.3)  # Стабилизация между шагами
        
        return self.validate_result()

Такая структура позволяет гибко управлять процессом выполнения теста и обрабатывать различные типы действий пользователя.

Как модули работают вместе

Эффективное взаимодействие всех модулей системы обеспечивает комплексный подход к тестированию, выявлению и устранению сбоев.

Обработка сбоев и зависаний

В арсенале системы автотестирования одну из ключевых функций выполняет модуль, занимающийся обнаружением и управлением сбоями программы. Этот модуль, работая в тандеме с инструментами для мониторинга состояния приложений, выступает в роли наблюдателя за стабильностью работы ПО.

Он автоматически анализирует текущее состояние приложения, используя скриншоты и проверку активности окон, чтобы определить отклонения от нормы. При обнаружении проблемы модуль оперативно реагирует, останавливая затронутый процесс и запуская процедуру его перезапуска через скрипт PowerShell, что позволяет минимизировать простои.

Управление окнами и процессами

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

Сравнение и анализ данных

Модуль сравнения данных предоставляет необходимые инструменты для глубокого анализа и обнаружения отклонений, включая визуальный анализ и сравнение файлов. Благодаря этому возможно эффективное выявление и устранение сбоев, что способствует поддержанию работоспособности системы.

Упрощённая логика модуля сравнения

Модуль анализа выполняет различные типы проверок в зависимости от настроек теста:

class ResultValidator:
    def __init__(self, config):
        self.validation_config = config
        self.reference_data = None
    
    def validate(self):
        method = self.validation_config.get("method")
        
        if method == "visual_compare":
            # Визуальное сравнение с эталоном
            expected = load_image(self.validation_config["expected_image"])
            actual = capture_current_screen()
            threshold = self.validation_config.get("threshold", 0.95)
            
            similarity = calculate_image_similarity(expected, actual)
            return similarity >= threshold
        
        elif method == "element_present":
            # Проверка наличия элемента на экране
            pattern = self.validation_config["pattern"]
            return find_element_on_screen(pattern) is not None
        
        elif method == "file_exists":
            # Проверка существования файла
            filepath = self.validation_config["filepath"]
            return os.path.exists(filepath)
        
        elif method == "no_validation":
            # Тест считается успешным при завершении
            return True
        
        return False

Координатор тестирования управляет выполнением и проверкой:

class TestCoordinator:
    def __init__(self, scenario):
        self.scenario = scenario
        self.player = ScenarioPlayer(scenario)
        self.validator = None
    
    def run_test(self):
        # Выполнение сценария
        self.player.execute_scenario()
        
        # Проверка результата
        if "validation" in self.scenario:
            self.validator = ResultValidator(self.scenario["validation"])
            result = self.validator.validate()
            
            if not result:
                self.save_failure_artifacts()
                self.log_error(self.scenario["test_name"])
            
            return result
        
        return True

Интеграция различных модулей в системе автотестирования создает условия для надежного и точного тестирования программного обеспечения. Взаимодействие этих модулей позволяет обеспечить комплексный подход к проверке ПО, учитывая разнообразные сценарии использования и потенциальные проблемы.

Вспомогательные компоненты

В рамках проекта автотестирования мы разработали несколько ключевых компонентов, каждый из которых играет свою роль в улучшении и упрощении процесса тестирования САПР-приложений.

Отчёты и уведомления

Модуль, отвечающий за создание сообщений о результатах тестов, позволяет формировать как текстовые, так и HTML отчёты. Это дает команде возможность глубже анализировать результаты тестирования и делиться ими в удобном формате.

Логирование событий и отправка отчётов по электронной почте интегрированы с основным процессом тестирования, что позволяет в реальном времени отслеживать процесс тестирования и оперативно реагировать на любые события.

Анализ результатов

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

Управление настройками

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

Работа с файлами

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

Автоматизация рутины

Скрипты PowerShell оказались незаменимыми в автоматизации ряда задач, связанных с подготовкой и выполнением тестов, а также очисткой тестового окружения после их завершения. Это включает в себя управление языковыми настройками, запуск и удаление приложений, что существенно повышает эффективность всего процесса тестирования.

Параллельное выполнение

Один из ключевых моментов - возможность запускать несколько т��стов одновременно. Для ускорения тестирования была использована многопоточная обработка, которая запускает несколько тестов одновременно. Вместо стандартных подходов был использован пул потоков, который управляет потоками, контролирует выполнение и обрабатывает ошибки.

Таким образом тестирование проходит быстрее, процессор используется эффективнее, а ошибки в одном тесте не мешают другим. Запускаем несколько виртуалок одновременно. Каждая гоняет свой набор тестов. Результаты собираются в конце.

Что получилось в итоге

Наш проект создал комплексную систему, ориентированную на автоматизацию и упрощение процесса тестирования САПР-приложений. Сочетание модульности, гибкости и интеграции различных инструментов и методик позволяет не только повышать качество программных продуктов, но и делать процесс тестирования более эффективным и удобным для команды.

Результатом стала система, которая не только улучшила процесс тестирования, но и показала, как правильный подход к выбору инструментов может значительно повлиять на исход проекта.

Куда двигаться дальше

Перспективы для дальнейшего развития проекта обширны и включают в себя углубление и расширение каждого уровня архитектуры:

Развитие функциональности: Разработка новых функциональных возможностей для автоматизации более сложных тестовых сценариев и интеграция с дополнительными инструментами САПР для расширения охвата тестирования.

Улучшение работы с данными: Усиление механизмов сбора, хранения и анализа тестовых данных для более глубокого понимания результатов тестирования и выявления тонких дефектов ПО.

Переход на Linux: Масштабирование тестирования с переходом на операционные системы Linux, повышение доступности и удобства использования. Переход на Linux позволит универсализировать тестовое окружение и оптимизировать использование ресурсов.

Применение AI: Использование передовых методов программирования и технологий, таких как машинное обучение и искусственный интеллект, для автоматизации анализа результатов тестирования и оптимизации процессов тестирования. Развитие кросс-платформенного тестирования усилит универсальность и гибкость системы.

Интеграция с CI/CD: Интеграция с системами контроля версий улучшит процессы управления исходным кодом и сотрудничество в команде. Хотелось бы привязать к Jenkins/GitLab - чтобы после каждого коммита автоматом запускались тесты.

Совершенствование визуализации: Разработка более совершенных методов работы с данными, включая их визуализацию и интерпретацию, для улучшения качества принятия решений на основе результатов тестирования.

Внедрение графического интерфейса на основе Qt для инструментов управления и анализа открывает новые возможности для удобства работы пользователей и кроссплатформенности, в том числе использование в Linux.

Заключение

Таким образом, проект автотестирования для САПР не только демонстрирует возможности современных технологий в области тестирования программного обеспечения, но и открывает новые горизонты для дальнейшего развития и усовершенствования процессов разработки и тестирования. Переход на Linux и интеграция с современными инструментами предоставляют уникальные возможности для расширения и углубления функциональности системы автотестирования, делая ее еще более мощным инструментом в руках разработчиков и тестировщиков.

Обширные перспективы развития проекта включают в себя комплексные улучшения на всех уровнях системы, от инструментария и методик до инфраструктуры и программной архитектуры. Эти направления развития не только повышают эффективность и гибкость процесса тестирования, но и обеспечивают его адаптацию к современным требованиям и технологическим трендам в разработке ПО.


Команда разработки: Толмачев Кирилл, Ларина Татьяна, Вараксин Максим, Чернолеций Кирилл, Трушкова Мария, Вяткин Роман