Статьи

Охота на тестовые рамки SWT? Передай привет оленю

Это первая из серии публикаций о новой платформе открытого тестирования Eclipse «Красный олень» ( https://github.com/jboss-reddeer/reddeer ). В этой статье мы расскажем о Red Deer и рассмотрим некоторые преимущества, которые он предлагает, создав тестовую программу с нуля.

Вот некоторые из функций, которые предлагает Red Deer: 

  • Простой в использовании высокоуровневый API для тестирования стандартных компонентов Eclipse
  • Поддержка создания пользовательских расширений для ваших собственных приложений
  • Механизм проверки требований, помогающий настраивать сложные тесты
  • Eclipse Tooling, чтобы помочь в создании новых проектов
  • Инструмент записи и воспроизведения, позволяющий быстро создавать автоматизированные тесты
  • Интеграция с Selenium для тестирования веб-приложений
  • Поддержка запуска тестов в среде Jenkins CI

Обратите внимание, что на момент написания статьи, Red Deer находится в стадии инкубации. Текущая версия находится на уровне 0.5. Ориентировочная дата релиза Red Deer 1.0 — конец 2014 года. Но, как проект с открытым исходным кодом для сообщества, сейчас самое подходящее время попробовать Red Deer и внести предложения или даже добавить код!

Взгляд на архитектуру оленя

Сам проект Red Deer состоит из утилит и API, который поддерживает разработку и выполнение автоматизированных тестов.

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

  • Верхний слой состоит из расширений абстрактных классов Red Deer или реализаций компонентов Eclipse, таких как Views, Editors, Wizards или Shells. Например, если вы пишете тесты для функции, которая использует пользовательский Eclipse View, вы можете расширить класс Red Deer View, добавив поддержку определенных функций этой функции. Преимущество этого уровня API в том, что ваши тестовые программы не должны фокусироваться на манипулировании отдельными элементами пользовательского интерфейса напрямую для выполнения операций. Вместо этого ваши программы могут создавать экземпляры компонента Eclipse, такие как View, а затем использовать методы этого экземпляра для выполнения операций над View. Этот уровень абстракции облегчает написание, понимание и сопровождение ваших тестовых программ.
  • Средний уровень состоит из реализаций Red Deer для таких элементов пользовательского интерфейса SWT, как: Кнопка, Комбо, Метка, Меню, Оболочка, TabItem, Таблица, Панель инструментов, Дерево. Этот уровень API поддерживает более высокий уровень API, предоставляя строительные блоки для представлений API, редакторов, оболочек и WIzards. Этот средний уровень API также предоставляет пакеты Red Deer, которые позволяют вашим тестам обеспечивать выполнение требований, поэтому перед запуском теста выполняются необходимые задачи настройки.
  • Нижний слой состоит из пакетов Red Deer, которые поддерживают выполнение тестов, таких как: Условия, Соответствия, Виджеты, Workbench и Расширения Red Deer для JUnit.

Что отличает красных оленей от других инструментов? Слой абстракции

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

Например, для теста, который должен открыть вид и нажать кнопку, без Red Deer, тест должен будет перемещаться по меню верхнего уровня, находить меню вида, затем тип представления в этом меню, а затем находить вид открытым диалоговое окно, затем найдите кнопку «ОК» и т. д. Ваш тест должен будет потратить много времени на навигацию по элементам пользовательского интерфейса, прежде чем он сможет начать выполнять шаги теста.

В Red Deer код для открытия представления (в данном случае представления серверов) просто:

ServersView view = new ServersView();
view.open();

Кроме того, внутри этого ServersView ваша тестовая программа может выполнять операции над View с помощью методов, которые определены в представлении (и, кстати, также хорошо отлажены командой Red Deer), вместо того, чтобы явно обнаруживать и манипулировать элементами UI напрямую. Например, чтобы получить список всех серверов, вместо того чтобы найти дерево пользовательского интерфейса, содержащее список серверов, и извлечь этот список серверов в массив, ваша программа Red Deer может просто вызвать метод «getServers ()».

Аналогично, код для открытия PackageExplorer, а затем выбора проекта в этом PackageExplorer выглядит следующим образом:

PackageExplorer packageExplorer = new PackageExplorer();
packageExplorer.open();
packageExplorer.getProject("myTestProject").select();

И код для извлечения всех проектов в этом PackageExplorer просто:

packageExplorer.getProjects();

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

Установка благородного оленя

Единственными предпосылками для использования Red Deer являются Eclipse и Java. В этом посте мы будем использовать Eclipse Kepler и OpenJDK 1.7, работающие на Red Hat Enterprise Linux (RHEL) 6.

Чтобы установить Red Deer 0.4 (это последняя стабильная веха версия на момент написания этой статьи), выполните следующие действия:

  • Откройте Eclipse
  • Перейдите к: Справка-> Установить новое программное обеспечение
  • Определите новый сайт загрузки с помощью URL сайта обновления Red Deer: http://download.jboss.org/jbosstools/updates/stable/kepler/core/reddeer/0.4.0/
  • Выберите Red Deer, нажмите кнопку Готово, и Red Deer установит

Теперь, когда у вас установлен Red Deer, давайте перейдем к созданию нового теста Red Deer.

Построение вашего первого теста на оленя

Чтобы создать новый тестовый проект Red Deer, вы используете инструмент интерфейса Red Deer и выбираете New-> Project-> Other-> Red Deer Test:

Прежде чем мы продолжим, давайте взглянем на файл WEB-INF / MANIFEST.MF, созданный в проекте:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.example.reddeer.sample
Bundle-SymbolicName: com.example.reddeer.sample;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-ActivationPolicy: lazy
Bundle-Vendor: Sample Co
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.junit, org.jboss.reddeer.junit, org.jboss.reddeer.swt, org.jboss.reddeer.eclipse

Строка, которая нас интересует, является последней строкой в ​​файле. Это связки, которые требуются Red Deer.

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

package com.example.reddeer.sample;  
  
import static org.junit.Assert.assertFalse;  
import java.util.List;  
import org.jboss.reddeer.swt.api.TreeItem;  
import org.jboss.reddeer.swt.impl.button.PushButton;  
import org.jboss.reddeer.swt.impl.menu.ShellMenu;  
import org.jboss.reddeer.swt.impl.tree.DefaultTree;  
import org.junit.Test;  
import org.junit.runner.RunWith;  
import org.jboss.reddeer.junit.runner.RedDeerSuite;  
  
@RunWith(RedDeerSuite.class)  
public class SimpleTest {  
  
   @Test  
   public void TestIt() {  
      new ShellMenu("Help", "About Eclipse Platform").select();  
      new PushButton("Installation Details").click();  
      DefaultTree ConfigTree = new DefaultTree();  
      List<TreeItem> ConfigItems = ConfigTree.getAllItems();  
  
      assertFalse ("The list is empty!", ConfigItems.isEmpty());  
      for (TreeItem item : ConfigItems) {  
          System.out.println ("Found: " + item.getText());  
      }  
   }  
}

После сохранения исходного файла теста вы можете запустить тест. Чтобы запустить тест, выберите опцию Run As-> Red Deer Test:

И — есть зеленая полоса!

Упрощение тестов с требованиями

Требования Red Deer позволяют вам определять действия, которые вы хотите выполнить перед выполнением теста. Преимущество использования требований заключается в том, что вы определяете действия с аннотациями вместо использования метода @BeforeClass. В результате ваш тестовый код легче читать и поддерживать. Самое большое отличие между требованием Red Deer и аннотацией @BeforeClass из среды JUnit состоит в том, что если требование не может быть выполнено, тест не выполняется.

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

В текущем выпуске Red Deer представлены заранее определенные требования, которые позволяют очистить текущее рабочее пространство и открыть перспективу. Давайте добавим это к нашему примеру.

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

import org.jboss.reddeer.eclipse.ui.perspectives.JavaBrowsingPerspective;
import org.jboss.reddeer.requirements.cleanworkspace.CleanWorkspaceRequirement.CleanWorkspace;
import org.jboss.reddeer.requirements.openperspective.OpenPerspectiveRequirement.OpenPerspective;

И эти аннотации:

@CleanWorkspace
@OpenPerspective(JavaBrowsingPerspective.class)

И мы также должны сослаться на org.jboss.reddeer.requirements на требуемый список комплектов в файле MANIFEST.MF нашего примера:

Require-Bundle: org.junit, org.jboss.reddeer.junit, org.jboss.reddeer.swt, org.jboss.reddeer.eclipse, org.jboss.reddeer.requirements

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

package com.example.reddeer.sample;

import static org.junit.Assert.assertFalse;
import java.util.List;
import org.jboss.reddeer.swt.api.TreeItem;
import org.jboss.reddeer.swt.impl.button.PushButton;
import org.jboss.reddeer.swt.impl.menu.ShellMenu;
import org.jboss.reddeer.swt.impl.tree.DefaultTree;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jboss.reddeer.junit.runner.RedDeerSuite;
import org.jboss.reddeer.eclipse.ui.perspectives.JavaBrowsingPerspective;
import org.jboss.reddeer.requirements.cleanworkspace.CleanWorkspaceRequirement.CleanWorkspace;
import org.jboss.reddeer.requirements.openperspective.OpenPerspectiveRequirement.OpenPerspective;

@RunWith(RedDeerSuite.class)
@CleanWorkspace
@OpenPerspective(JavaBrowsingPerspective.class)

public class SimpleTest {
   @Test
   public void TestIt() {
       new ShellMenu("Help", "About Eclipse Platform").select();
       new PushButton("Installation Details").click();
       DefaultTree ConfigTree = new DefaultTree();
       List<TreeItem> ConfigItems = ConfigTree.getAllItems();

       assertFalse ("The list is empty!", ConfigItems.isEmpty());
       for (TreeItem item : ConfigItems) {
           System.out.println ("Found: " + item.getText());
       }
   }
}

Обратите внимание, как мы смогли добавить эти функции в тестовый код, добавив при этом лишь очень небольшое количество фактического нового кода? Да, это может быть платой, чтобы быть ленивым программистом. 😉 

Что дальше?

Следующим этапом развития Red Deer станет его дальнейшее развитие по мере прохождения стадии инкубации до выпуска 1.0. Что будет дальше для этой серии постов, будут обсуждаться:

  • Red Deer Recorder — позволяет вам захватывать ручные действия и преобразовывать их в тестовые программы
  • Как вы можете расширить Red Deer — чтобы обеспечить тестовое покрытие для конкретных функций ваших плагинов.
  • И как вы можете внести эти расширения в проект Red Deer.
  • Как вы можете определить сложные требования — чтобы вы могли выполнять задачи настройки для ваших тестов.
  • Интеграция Red Deer с Selenium — чтобы вы могли тестировать веб-интерфейсы, предоставляемые вашими плагинами.
  • Выполнение тестов Red Deer с Jenkins — чтобы вы могли воспользоваться преимуществами инфраструктуры тестирования Jenkins Continuous Integration (CI).

Благодарности автора

Я хотел бы поблагодарить всех участников Red Deer за их видение и вклад. Это новый проект, но он быстро растет! Авторы (в алфавитном порядке): Стефан Бансиак, Радим Хопп, Ярослав Янкович, Люсия Елинкова, Мариан Лабуда, Мартин Малина, Ян Недерман, Владо Пакан, Иржи Петерка, Андрей Подградский, Милос Прчлик, Радослав Рабара, Петр Суши и Рат Вагнер.