Статьи

Тестирование Eclipse GUI возможно с SWTBot

В течение нескольких лет я боролся с жизнеспособностью автоматизированных структур тестирования Eclipse GUI. Теперь я впервые нашел подход, который работает надежно. В этой статье обсуждается подход и подробно описываются некоторые конкретные методы, которые значительно повышают производительность при создании полезных тестов.

В прошлом рамки автоматизированного тестирования GUI не соответствовали моим потребностям, потому что они были слишком сосредоточены на записи и воспроизведении. Сложность среды Eclipse делает практически невозможным надежную работу этого подхода. Простые вещи, такие как фоновые задания и обработка, становятся основными проблемами. Тестирование редакторов на основе GEF невозможно, поскольку все структуры записи / воспроизведения основаны на идентификации элементов управления и виджетов, которые GEF не использует.

Недавно я наткнулся на SWTBot , который использует новый подход. Тесты SWTBot написаны на Java и выполняются внутри процесса Eclipse как тестовое приложение Eclipse. Это дает SWTBot полный доступ к API-интерфейсам SWT и Eclipse. Тесты SWTBot написаны как JUnits, что упрощает интеграцию с распространенными технологиями, такими как Ant, Continuous Integration и инструменты покрытия кода.

Но не все так радужно при написании тестов с SWTBot. Есть некоторые специфические особенности Eclipse, которые возвращаются, чтобы укусить вас, такие как контекстные меню, которые восстанавливаются при показе, и структура GEF, которая не использует элементы управления или виджеты. Тем не менее, SWTBot обеспечивает и отличную отправную точку. Вот как я построил SWTBot для создания мощной тестовой среды, которая проста в использовании.

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


public void resetPerspective() {
bot.menu("Window").menu("Reset Perspective...").click();
bot.shell("Reset Perspective").activate();
bot.button("OK").click();
}

Неплохо! Легко увидеть, что происходит. В других случаях код выглядел больше так:


SWTBotTree tree = bot.tree();
String[] path = name.split("/");
SWTBotTreeItem[] items = tree.getAllItems();
SWTBotTreeItem selectedItem = null;
for (SWTBotTreeItem item: items) {
if (path[0].equals(item.getText())) {
item.expand();
sleep();
selectedItem = item;
break;
}
}
for (int x = 1;selectedItem != null && x

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

Вот что я сделал, чтобы сделать вещи проще:

1. Создайте классы, которые напрямую моделируют части пользовательского интерфейса, с которыми вы работаете в своих тестах. Например, вместо непосредственного использования SWTBotView для управления представлением Package Explorer, создайте класс PackageExplorer, который делегирует SWTBotView и предоставляет более широкие функциональные возможности. Например, в моем классе PackageExplorer у меня есть следующий метод:


/**
* select the first element that adapts to the given resource
*/
public void select(final IResource resource)

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

3. Вместо того, чтобы использовать sleep (), чтобы ждать, пока что-то будет сделано, подождите, пока что-то будет сделано. Сильно загруженная машина может привести к изменению времени обработки. Вместо хрупкого сна (500 л) используйте надежную технику, чтобы определить, когда работа действительно выполнена.

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


// ensure that all queued workspace operations and locks are released
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// nothing to do!
}
}, new NullProgressMonitor());

4. Используйте и расширяйте структуру SWTBot с помощью поведения, специфичного для Eclipse. Например, используйте API условного ожидания SWTBot, создавая специфичные для Eclipse условия, подобные этим, которые используются для ожидания открытия редактора на ресурсе:


/**
* a condition that is used to wait for an editor to open on a specific file.
*
* @author dgreen
*/
public class EditorOpenCondition extends DefaultCondition {
private final IFile file;

public EditorOpenCondition(IFile file) {
this.file = file;
}

public String getFailureMessage() {
return String.format("Timed out waiting for editor on %s to open",file.getFullPath());
}

public boolean test() throws Exception {
if (!file.exists()) {
return false;
}
return UIThreadRunnable.syncExec(new UIThreadRunnable.BoolResult() {
public boolean run() {
IEditorReference[] editorReferences = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
for (IEditorReference reference: editorReferences) {
try {
IEditorInput input = reference.getEditorInput();
if (input instanceof IFileEditorInput) {
IFileEditorInput editorInput = (IFileEditorInput) input;
if (editorInput.getFile().equals(file)) {
return true;
}
}
if (input instanceof IStorageEditorInput) {
IStorageEditorInput editorInput = (IStorageEditorInput) input;
IPath fullPath = editorInput.getStorage().getFullPath();
if (fullPath.equals(file.getFullPath())) {
return true;
}
}
} catch (PartInitException e) {
e.printStackTrace();
} catch (CoreException e) {
e.printStackTrace();
}
}
return false;
}
});
}
}

5. Создайте DSL на основе Java для часто повторяемого использования редакторов или представлений. Например, для редактора статических диаграмм классов вы можете получить DSL, который можно использовать следующим образом:


DomainModelDsl domainModelDsl = new DomainModelDsl();
domainModelDsl.create(project, "domain.dm");

domainModelDsl.
createEntity("A").
createEntity("B");

domainModelDsl.entity("A").extension("B");

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

6. Создайте ваперы GEF EditPart. Для редакторов на основе GEF SWTBot не очень помогает. Для этого вам нужно создать классы, аналогичные классам, предоставляемым SWTBot, но вместо того, чтобы фокусироваться на виджетах, они должны быть ориентированы на EditPart.

 

В целом я очень впечатлен SWTBot, который наконец-то предоставил жизнеспособную автоматизированную среду тестирования GUI для приложений Eclipse и Eclipse RCP. Я рад видеть, что SWTBot внес предложение по проекту Eclipse , которое, если оно будет одобрено, приведет к дальнейшим улучшениям и принятию сообществом.

С
http://greensopinion.blogspot.com