Tox Ansible#
Tox Ansible – это расширение для Tox, позволяющее использовать его для тестирования коллекций Ansible с различными версиями Python и Ansible без использования контейнеров, виртуальных машин и тестовых стендов.
Ключевые особенности и достоинства#
Tox Ansible имеет следующие ключевые особенности и достоинства:
Поддержка мультиверсионного тестирования.
Tox Ansible позволяет тестировать коллекции сразу на нескольких версиях Python и Ansible.
Интеграция с инструментами тестирования Python.
Tox Ansible позволяет проводить следующие типы тестов:
sanity
– проверка качества кода и соответствия стандартам;unit
– модульное тестирование;integration
– интеграционное тестирование.
Для проведения тестирования используются следующие инструменты:
tox
– управляет тестовыми средами;ansible-test
– проводит тесты типаsanity
;pytest
– выполняет тесты типовunit
иintegration
.
Локальное тестирование.
Тестовые окружения сохраняются после завершения тестирования. Это сокращает время на развертывание окружений.
Простота управления тестовыми окружениями.
Все виртуальные окружения создаются внутри каталога
.tox/
. Если нужно, эти окружения можно легко удалить или пересоздать без дополнительных настроек.
Установка#
Для установки Tox Ansible выполните следующие действия:
Подключите репозиторий Astra Automation.
Инструкция по подключению репозитория
В каталоге
/etc/apt/sources.list.d/
создайте файлastra-automation.list
со ссылкой на репозиторий Astra Automation:deb https://dl.astralinux.ru/aa/aa-debs-for-alse-1.8 <version> main
Вместо <version> необходимо подставить версию устанавливаемой платформы, например,
1.2
.Доступные версии продукта опубликованы в таблице История обновлений.
Обновите список доступных пакетов:
sudo apt update
Выполните команду:
sudo apt-get install tox-ansible --yes
Установка при отсутствии доступа к интернету описана в документе Разработка контента и среды исполнения.
Принцип работы#
Работа с Tox Ansible начинается с создания в корневом каталоге проекта файла настроек tox-ansible.ini
.
В этом файле указываются следующие параметры:
тестовые окружения;
зависимости;
тесты, которые должны быть выполнены в каждом виртуальном окружении.
Если не требуется переопределение настроек, файл может быть пустым, но его присутствие обязательно.
Параметры запуска Tox Ansible также можно задать с помощью аргументов командной строки.
Настройки из аргументов командной строки имеют более высокий приоритет, чем указанные в файле tox-ansible.ini
.
Параметры в файле настроек задаются как в следующем примере:
[tox]
envlist =
unit-py37-ansible2.9,
unit-py37-ansible2.10,
integration-py37-ansible2.9,
integration-py37-ansible2.10
[testenv]
basepython =
py37: python3.7
deps =
ansible2.9: ansible==2.9.*
ansible2.10: ansible==2.10.*
commands = pytest tests
Подробное описание параметров файла настроек см. в справочнике.
При запуске Tox Ansible выполняет следующие действия:
Определяет список тестовых окружений, указанных в файле настроек.
Для каждого тестового окружения создает изолированное виртуальное окружение с соответствующей версией Python.
Устанавливает зависимости, указанные для каждого тестового окружения.
Запускает тесты внутри каждого виртуального окружения.
Собирает и выводит результаты тестирования.
Примеры#
Для изучения работы Tox Ansible на практике в вашей системе должен быть предварительно установлен Python версий 3.11. При отсутствии в системе необходимой версии Python тесты для нее будут пропущены.
Базовый сценарий#
Типичный сценарий применения Tox Ansible содержит следующие шаги:
Создайте коллекцию
my_collection
:ansible-galaxy collection init my_namespace.my_collection
Перейдите в каталог
roles/
:cd my_namespace/my_collection/roles/
Создайте роль
test_role
:ansible-galaxy init test_role
Добавьте в файл
main.yml
следующие данные:--- - name: Message Hello Role ansible.builtin.debug: msg: "Hello collection"
Перейдите в каталог
my_collection/
:cd ..
В файле
/my_namespace/my_collectionmeta/runtime.yml
раскомментируйте строку:requires_ansible: '>=2.9.10'
В каталоге
my_collection/
создайте сценарийhello_collection.yml
со следующим содержимым:--- - name: Test Role hosts: localhost roles: - test_role
Создайте файл
tests/test_sanity.py
c тестом типаsanity
test_sanity.py#import ansible_runner def test_hello_collection(): result = ansible_runner.run(private_data_dir=".", playbook="hello_collection.yml") assert result.rc == 0, f"Сценарий завершился с ошибкой: {result.rc}" # Проверка наличия "Hello collection" в stdout assert any( "Hello collection" in event.get("stdout", "") for event in result.events ), "Сообщение 'Hello collection' не найдено в выводе"
Создайте файл
tests/integration/test_integration.py
c тестом типаintegration
:test_integration.py#import subprocess import unittest class TestHelloCollectionIntegration(unittest.TestCase): def test_playbook_integration(self): """Проверка интеграции сценария и роли.""" playbook_path = "<path_to_hello_collection.yml>" # Выполнение сценария через ansible-playbook result = subprocess.run( ["ansible-playbook", playbook_path], capture_output=True, text=True, check=True, ) # Проверка кода завершения self.assertEqual( result.returncode, 0, f"Сценарий завершился с ошибкой: {result.stderr}" ) # Проверка, что в выводе содержится ожидаемое сообщение self.assertIn( "Hello collection", result.stdout, "Сообщение 'Hello collection' не найдено в выводе.", ) if __name__ == "__main__": unittest.main()
Здесь <path_to_hello_collection.yml> – путь к сценарию
hello_collection.yml
, созданному ранее.Создайте файл
tests/unit/test_unit.py
c тестом типаunit
:test_unit.py#import unittest def hello_message(): return "Hello collection" class TestHelloFunction(unittest.TestCase): def test_hello_message(self): """Проверка, что функция возвращает правильное сообщение.""" self.assertEqual(hello_message(), "Hello collection") if __name__ == "__main__": unittest.main()
Создайте файл
tox-ansible.ini
со следующим содержимым:[tox] envlist = sanity-py3.11-ansible2.9, unit-py3.11-ansible2.9, integration-py3.11-ansible2.9 skipsdist = true [testenv:sanity-py3.11-ansible2.9] basepython = python3.11 deps = ansible==2.9 pytest ansible-runner commands = pytest tests/test_sanity.py allowlist_externals = ansible-playbook mkdir bash [testenv:unit-py3.11-ansible2.9] basepython = python3.11 deps = ansible==2.9 pytest ansible-runner commands = pytest tests/unit/test_unit.py allowlist_externals = ansible-playbook mkdir bash [testenv:integration-py3.11-ansible2.9] basepython = python3.11 deps = ansible==2.9 pytest ansible-runner commands = pytest tests/integration/test_integration.py allowlist_externals = ansible-playbook mkdir bash
Просмотрите список всех окружений, определенных в файле настроек:
tox list --conf tox-ansible.ini
Пример вывода
Запустите утилиту:
Для всех типов тестов:
tox -r --conf tox-ansible.ini
C фильтром по типу теста:
tox -f unit -r --conf tox-ansible.ini
Дождитесь завершения выполнения тестирования, это может занять некоторое время. Тестирование считается успешным, если для всех тестовых сред указано значение
OK
.Пример части вывода
sanity-py3.11-ansible2.9: OK (14.09=setup[12.32]+cmd[1.77] seconds) unit-py3.11-ansible2.9: OK (10.98=setup[10.80]+cmd[0.18] seconds) integration-py3.11-ansible2.9: OK (13.33=setup[11.71]+cmd[1.62] seconds) congratulations :) (38.47 seconds)
Передача аргументов#
Tox Ansible автоматически запускает ansible-test
для тестов типа sanity
или pytest
для тестов типа unit
и integration
.
Однако иногда нужно настроить запуск этих тестов, добавив дополнительные аргументы.
Чтобы передать аргументы для ansible-test
, используйте следующую команду:
tox -f sanity --ansible --conf tox-ansible.ini -- --test validate-modules -vvv
Здесь:
-f
– фильтр тестов. В этом примере используется фильтр типаsanity
.--ansible
– аргумент, активирующий поддержку Ansible.--
– разделитель. Все, что идет после разделителя, передается как аргументы дляansible-test
.--test
– название теста который необходимо запустить.-vvv
– повышение детализации вывода.
Чтобы передать аргументы для pytest
, используйте следующую команду:
tox -e unit-py3.11-2.14 --ansible --conf tox-ansible.ini -- --junit-xml=tests/output/junit/unit.xml
Здесь:
-e
– окружение для тестов:unit
– тип тестов.py3.11
– версия Python.2.14
– версия Ansible.
--
– разделитель. Все, что идет после разделителя, передается как аргументы дляpytest
.--junit-xml=tests/output/junit/unit.xml
– путь для сохранения отчета о тестировании в формате XML.