Русский
Русский
English
Статистика
Реклама

Из песочницы Автоматизация системных тестов на базе QEMU (Часть 12)

Эта статья посвящена автоматизации системного (end-to-end) тестирования с использованием виртуальных машин. В статье рассматриваются такие вопросы, как автоматизация развертывания и настройки виртуальных стендов, а также автоматизация запуска процессов внутри виртуальных машин с последующим контролем полученных результатов. В конце статьи мы получим пусть неидеальный (к этому мы ещё вернемся), но простой и понятный скрипт, с помощью которого вы сможете запускать системные тесты одной кнопкой, даже не имея у себя на компьютере ни одной виртуальной машины.


Статья предполагает наличие следующих навыков у читателя:


  • Уверенное пользование ОС семейства Linux;
  • Базовое понимание принципов виртуализации;
  • Знакомство с гипервизором QEMU и графическим клиентом virt-manager

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


Дисклеймер

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


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


Что такое системное тестирование


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


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


  • Вид и версия ОС;
  • Разные настройки ОС (например, в области разграничения прав доступа);
  • Наличие или отсутствие определенных программ в ОС (в т.ч. драйверов);
  • Наличие сети и других компьютеров в ней;
  • Количество оперативной памяти или определённая архитектура процессора.

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


Почему именно виртуалки?


Может возникнуть вопрос, а зачем использовать именно виртуалки? Ведь для воспроизведения окружения для программы можно использовать и контейнеры (например, если Вас интересует поведение программы в связке с другими программами). И действительно, для контейнеров существует несколько решений по автоматизации тестов. Однако, существуют классы сценариев, которые нельзя протестировать с помощью контейнеров:


  1. Нельзя протестировать приложения не под Linux, а также гетерогенные стенды из нескольких машин;
  2. Нельзя протестировать GUI (или даже псевдо-GUI);
  3. Нельзя протестировать драйвера и работу с оборудованием.

Автоматизация пунктов 1 и 2 потребует от нас существенной подготовки, поэтому оставим их для одной из следующих статей. А вот для пункта 3 вполне хватит той информации, которую Вы узнаете из этой статьи. В этой статье (во второй её части) мы как раз продемонстрируем автоматизацию тестирования приложения, которое взаимодействует с оборудованием напрямую, в обход операционной системы.


Какой выбрать гипервизор?


В целом, схема, которую мы предложим в этой статье, применима к любому гипервизору. Но мы воспользуемся QEMU, потому что он позволит нам получить работающий прототип затратив при этом минимальные усилия и время. Основные принципы и идеи из этой статьи, при желании, можно реализовать и на других гипервизорах (например, на VirtualBox).


Какие действия мы хотим автоматизировать?


Для того, чтобы автоматизировать системные тесты, нам нужно решить как минимум следующие вопросы:


  1. Как автоматически создать виртуалку;
  2. Как "раскатать" и настроить ОС;
  3. Как научиться управлять виртуалкой после её установки. В частности, нас интересует, как запускать процессы внутри виртуалки и копировать на неё файлы.

Заметка про тестирование методом чёрного ящика

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


Что ж, погнали!


Создаем виртуалку


Конечно, я думаю все пробовали создавать виртуальные машины вручную. Для этого в графическом интерфейсе рисуются всякие диалоговые окна, где надо выбрать конфигурацию, диски, сетевые адаптеры и прочее прочее. Так вот, для гипервизора QEMU всё это можно сделать и в консольном режиме с помощью утилиты virt-install. Давайте посмотрим как будет выглядеть простейшее создание виртуальной машины с помощью этой утилиты:


virt-install \    --name my_super_vm \    --ram 1024 \    --disk my_super_vm.qcow2,size=8 \    --cdrom /path/to/ubuntu_server.iso

Вот такой простой командой мы можем создать виртуальную машину с именем my_super_vm, 1024 Мегабайтами оперативной памяти, новым диском my_super_vm.qcow2 размером 8 Гигабайт. В виртуальном CD-приводе такой машины будет смонтирован установочный образ ubuntu_server.iso (конечно, этот образ надо предварительно скачать), который, как обычно, нужен для установки ОС на свежесозданную виртуалку.


Впрочем, если Вы выполните такую команду, то увидите как у вас запустилось графическое окно с VNC-клиентом, который подключается к виртуальной консоли виртуальной машины. В этом окне Вы увидите начало установки Ubuntu Server 18.04. Конечно, реальный человек бы смог протыкать несколько клавиш на клавиатуре и установить Ubuntu Server, но мы лишены такой роскоши, ведь мы работаем исключительно консольными командами.


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


Создаём диск из шаблона


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


Вызов команды virt-install, приведённый выше, выполняет сразу два действия: он создаёт одновременно и машину и диск. Из-за может сложиться неверное впечатление, что эти сущности неотделимы друг от друга.


Но на самом деле никто не мешает нам отдельно создать виртуальный диск, а затем подключить его к виртуальной машине. Вы можете подготовить свой образ диска, но в этой статье мы для простоты воспользуемся уже готовым. Проект libguestfs поддерживает в свободном доступе целый репозиторий таких образов. Кроме того, в рамках этого же проекта существует утилита virt-builder, которая позволяет легко скачать нужный образ диска и доработать его "напильником" под наши нужды.


Несколько слов про проект libguestfs и почему стоит обратить на него внимание

В первую очередь Libguestfs это программная библиотека, которая позволяет легко манипулировать содержимым образом виртуальных дисков. Под манипуляцией подразумеваются такие операции как форматирование дисков, копирование файлов на диск и из него и так далее. Кроме того, в рамках проекта реализован целый набор утилит на все случаи жизни, которые используют различные возможности библиотеки. Среди них есть очень простые утилиты (в стиле Unix-way), которые выполняют всего одно действие, например virt-copy-in. С другой стороны есть команды-комбайны, которые умеют много всего и сразу, такие как virt-builder.


Итак, что же нам позволяет сделать virt-builder? С помощью этой утилиты мы можем на лету сформировать уже "подготовленный" диск с уже установленной Ubuntu Server. Сделать это можно так:


virt-builder ubuntu-18.04 \    --format qcow2 \    --output my_super_disk.qcow2

Что же здесь происходит? Мы говорим, что хотели бы создать диск в формате qcow2 (можно выбрать другой) и использовать в качестве основы шаблон ubuntu-18.04, который хранится в репозитории шаблонов в проекте libguestfs. Команда virt-builder скачает этот шаблон из Интернета и затем на его основе сгенерирует итоговый диск, в котором теперь будет установлен Ubuntu Server!


Кешируемость шаблонов

Приятной особенностью утилиты virt-builder является то, что шаблон диска кешируется после первого скачивания, поэтому последующие создания дисков будут проходить гораздо быстрее


Ну а теперь нам остаётся создать виртуальную машину, и указать в качестве диска (импортировать) подготовленный образ my_super_disk.qcow2:


virt-install \    --import \    --name my_super_vm \    --ram 1024 \    --disk my_super_vm.qcow2

Обратите внимание, что исчез параметр --cdrom, он нам больше не нужен. Также добавился параметр --import. Этот параметр указывает, что виртуалка будет загружаться не с cdrom, а с виртуального диска (то есть это влияет на Bios Boot Options виртуальной машины). Ну а т.к. диск у нас теперь содержит установленный Ubuntu Server, такая загрузка пройдёт успешно.


Попробуйте выполнить эти команды и создать таким образом виртуальную машину my_super_vm. Вы сможете убедиться, что Ubuntu Server 18.04 действительно уже установлен и успешно загружается.


Соединяем сетью виртуалку и хост


Вот так вот мы практически незаметно научились автоматически устанавливать виртуалки и даже раскатывать на них готовую ОС. Теперь настало время поговорить о канале управления виртуалкой после её установки и настройки.


Ещё раз хотелось бы отметить, что эталоном автоматизации системных тестов должна выступать автоматизация действий человека: как он нажимает на клавиши, кликает мышкой и совершает другие действия. И ещё раз напомним, что это очень сложный (хоть и правильный) путь. Мы же воспользуемся тем фактом, что нам не требуется взаимодействовать с GUI, нам пока вполне хватит возможности выполнения произвольных bash-команд на гостевой системе.


Для этого существуют разные подходы, но мы с Вами в этой статье рассмотрим только самый простой и, в некоторой степени, топорный вариант: установка SSH-соединения между хостом и виртуалкой.


Альтернативные подходы

Не всегда канал управления виртуалкой через ssh является приемлемым вариантом. Такое бывает, если Вы тестируете приложение, которое каким-то образом завязано на сетевую подсистему. Например, в случае если вы как раз таки и разрабатываете ssh-сервер. Вы же не хотите, чтобы Ваши тесты полагались на работоспособность ещё неготовой программы? Либо Вы хотите проверить, как поведёт себя Ваша программа на виртуалке, где вообще нет сетевых интерфейсов.


В качестве альтернативы можно управлять гостевой системой через последовательный порт. При этом последовательный порт образует как бы трубу (pipe), проложенную между хостом и виртуалкой. Со стороны Linux-хоста эта труба видна как unix-socket, а со стороны гостевой системы как последовательное устройство. Всё, что отправляется в один конец трубы, тут же появляется из другого. Соответственно, как и в случае с ssh, на гостевой системе должен работать некий сервер, ожидающий получения данных из последовательного порта. Примером такого сервера может служить qemu-guest-agent.


В случае, если Вы работаете с гипервизором Hyper-V, то помимо последовательного порта можно попробовать воспользоваться механизмом KVP (Key-Value Pairs) или Hyper-V Sockets.


Для этого нам потребуется сделать несколько манипуляций:


  1. Создать виртуальную сеть между хостом и виртуалкой;
  2. Настроить сетевой интерфейс на виртуалке;
  3. Задать пароль от пользователя root на виртуалке;
  4. Подредактировать SSH-настройке на виртуалке, чтобы можно было соединяться по SSH от имени рута с помощью пароля.

По поводу ssh без пароля

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


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


  1. Создать виртуальную сеть;
  2. Подключить виртуалку к этой сети (хост уже будет подключен к сети по-умолчанию).

Итак, поехали.


Для создания виртуальной сети мы воспользуемся ещё одной утилитой virsh, которая работает поверх ещё одной замечательной библиотеки libvirt.


Несколько слов про libvirt

Libvirt это, опять же, программная библиотека, предназначенная для управления гипервизорами. Проект libvirt ставит перед собой задачу объять необъятное сделать интерфейс управления, подходящий сразу для всех гипервизоров. Задача благая, но уж слишком амбициозная. На данный момент гипервизоры, отличные от QEMU, поддерживаются довольно слабо. Однако, если Вам требуется сделать что-то именно с QEMU, то проект libvirt и утилита virsh, входящая в его состав, являются самым быстрым и удобным вариантом.


В libvirt для создания различных виртуальных объектов (дисков, сетей, виртуалок) используются XML-схемы. XML-схема для создания сети выглядит примерно так:


<network>    <name>net_for_ssh</name>    <bridge name='net_for_ssh'/>    <ip address='192.168.100.1' netmask='255.255.255.0'/></network>

Где 192.168.100.1 это адрес, присваиваемый сетевому интерфейсу, который будет автоматически создан на хосте и ассоциирован с новой виртуальной сетью.


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


virsh net-define net_for_ssh.xml

После создания сеть создаётся в выключенном состоянии, поэтому её ещё надо включить:


virsh net-start net_for_ssh

Теперь надо подключить виртуалку к свежесозданной сети. Для этого при создании виртуалки необходимо добавить параметр --network:


virt-install \    --import \    --name my_super_vm \    --ram 1024 \    --disk my_super_vm.qcow2 \    --network network=net_for_ssh \    --noautoconsole

Обратите также внимание на аргумент --noautoconsole, который отключает автоматическое подключение к консоли виртуалки через VNC-клиент (впрочем, если Вам всё-равно хочется зайти посмотреть на виртуалку, Вы можете воспользоваться virt-manager).


Соединение готово, но пропинговать с хоста нашу виртуалку мы всё ещё не можем: сетевой интерфейс пока не настроен.


Настройка сетевого интерфейса на виртуалке


Как же мы будем настраивать интерфейс внутри виртуалки, если мы пока не можем выполнять на ней никаких команд (SSH-канал ведь ещё не настроен)? В этом нам снова поможет библиотека libguestfs и утилита virt-builder.


Дело в том, эта библиотека позволяет, в числе прочего, копировать файлы на виртуальный диск. Как мы знаем, в Ubuntu Server 18.04 за сетевые настройки отвечает netplan, и для того, чтобы сконфигурировать сетевой интерфейс, нам достаточно подложить специальный .yaml файлик в каталог /etc/netplan. И сделать это можно с помощью той же утилиты virt-builder с помощью параметра --copy-in:


Файл с настройками сетевого интерфейса netcfg_ssh.yaml
network:  version: 2  renderer: networkd  ethernets:    ens3:      addresses:        - 192.168.100.2/24

virt-builder ubuntu-18.04 \    --format qcow2 \    --output my_super_disk.qcow2 \    --copy-in netcfg_ssh.yaml:/etc/netplan/

И теперь при создании виртуального диска после раскатывания Ubuntu Server 18.04 из шаблона virt-builder дополнительно скопирует файл netcfg_ssh.yaml и подложит его в директорию /etc/netplan/ на файловой системе виртуального диска.


Теперь виртуальная машина должна пинговаться, проверим:


ping 192.168.100.2 -c5

Почти всё сделали, осталось лишь настроить SSH.


Настраиваем SSH на виртуалке


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


  1. Прописать пароль для root-пользователя в виртуалке;
  2. Создать ключи на виртуалке для SSH-сервера чтобы он стартовал без ругани;
  3. Прописать в конфиг SSH-сервера возможность подключаться от имени рута с использованием пароля.

Начнём с пароля для root. Здесь нас снова выручает virt-builder, который, на самом деле, позволяет Вам делать с виртуальным диском поистине удивительные вещи, одна из которых прописать пароль для root-пользоавтеля:


virt-builder ubuntu-18.04 \    --format qcow2 \    --output my_super_disk.qcow2 \    --root-password password:1111 \    --copy-in netcfg_ssh.yaml:/etc/netplan/

Теперь осталось сгенерировать ключи для SSH и подправить конфиг. Для этого нам надо всего-то надо выполнить пару команд:


ssh-keygen -Ased -i \"s/.*PermitRootLogin.*/PermitRootLogin yes/g\" /etc/ssh/sshd_config

Вот только вопрос, а как же нам выполнить эти команды? Ведь virt-builder работает только с образами дисков, никаких виртуальных машин на этом этапе не создаётся. Однако, уvirt-builder есть ещё пара козырей в рукаве. Он позволяет запускать программы гостевой системы без запуска собственно гостевой системы с помощью параметра --run-command:


virt-builder ubuntu-18.04 \    --format qcow2 \    --output my_super_disk.qcow2 \    --root-password password:1111 \    --run-command "ssh-keygen -A" \    --run-command "sed -i \"s/.*PermitRootLogin.*/PermitRootLogin yes/g\" /etc/ssh/sshd_config" \    --copy-in netcfg_ssh.yaml:/etc/netplan/

А как это работает?

Хороший вопрос. Документация libguestfs ничего не говорит нам о деталях реализации этого механизма, а исходники довольно запутаны. Но похоже, что здесь используется User Space Linux Kernel. Это не контейнеры, но очень на них похоже. В любом случае можно сделать следующие выводы:


  • в параметре --run-command можно смело вызвать любой бинарник, который есть на диске гостевой системы
  • при этом можно смело пользоваться сетью, например устанавливать пакеты с помощью apt install

И теперь всё! Канал настроен! Можно было бы даже попробовать подключиться, если бы не одно "но". После выполнения команды virt-install виртуалка только только начинает включаться. Между моментом включения виртуалки и запуском на ней ssh сервера может пройти несколько секунд. Поэтому нам потребуется организовать незатейливый механизм ожидания ssh сервера:


#!/bin/bashSSH_CMD="sshpass -p 1111 ssh -o StrictHostKeyChecking=no"while ! $SSH_CMD root@192.168.100.2 echo Hello world from my super vm!do    echo "Waiting for client VM ..."    sleep 1done

Также, мне пришлось добавить параметр -o StrictHostKeyChecking=no к команде ssh для того, чтобы запрос на добавление сервера в список доверенных серверов не блокировал выполнение скрипта. Так же мне пришлось воспользоваться утилитой sshpass для того, чтобы автоматизировать ввод пароля.


Итоги


В первой части статьи мы пока не написали ни одного реального системного теста, зато познакомились с серьёзным арсеналом утилит по работе с виртуальными машинами, научились автоматически создавать виртуалки, раскатывать на них ОС, настраивать их, а также налаживать канал управления по SSH. С этим запасом знаний мы теперь можем смело переходить к самому главному и интересному: как же, всё-таки, автоматизировать системные тесты на виртуалках.

Источник: habr.com
К списку статей
Опубликовано: 23.09.2020 12:10:47
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Тестирование it-систем

Виртуализация

Разработка под linux

Автоматизация тестирования

Qa automation

Qemu-kvm

Libvirt

Libguestfs

Ssh

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru