OpenQuality.ru

Качество программного обеспечения

Качество программного обеспечения: в главных ролях

Лента  Радар  Блог  Опыт  
Разум  Видео  Заметки  Эпизоды


Sikuli: обертки и свернутые сессии

Добрый день.

Тема Sikuli (инструмент для автоматизации действий в графическом интерфейсе) поднималась в блоге два года назад (запуск в среде Linux). Рассмотрим обертки вокруг базовых методов Sikuli и запуск тестов в свернутой RDP-сессии в среде Windows.

 

Обертки вокруг базовых методов Sikuli

При работе автотеста с Sikuli порой приходится ожидать или нажимать на элемент графического интерфейса, который может видоизменяться от запуска к запуску: на разных машинах, в разных браузерах, при разных исходных данных. К примеру, у элемента может различаться фон (белый, матовый, серый), форма представления (прямые или закругленные углы), шрифт текста (Times New Roman или Calibri). Еще один пример: интересующий нас элемент может частично перекрываться другим элементом при малом разрешении экрана или появлении неожидаемых окон. И при всем при этом нам нужно кликнуть на этот элемент вне зависимости от подобных отклонений. Как поступать в таких случаях?

Вариант в лоб: выделить ту часть элемента, которая не подвержена отклонениям. Если различается фон, то ориентироваться на кусок, на котором нет фона. Если различаются углы, то исключить углы из паттерна. Если элемент иногда перекрывается, то ориентироваться на кусок, который точно не перекроется и т.п. Вариант простой, но не всегда надежный. Порой не удается выделить “чистый” кусок элемента, который “ну уж точно не изменится”.

В таких случаях можно подготовить различные представления паттернов (картинок) в соответствии с вариациями элемента UI и воспользоваться простыми обертками вокруг методов wait и click. Вот два примера для wait без претензий на красоту кода:
 
1) В качестве параметра метода выступает список картинок, разделенных точкой с запятой. Для простоты изложения время ожидания каждой картинки зашито внутри метода (30 секунд). Что происходит в случае трех картинок (трех модификаций элемента): ждем первую картинку 30 секунд, затем вторую картинку 30 секунд, затем третью картинку 30 секунд. При нахождении любой из картинок выходим с Success.

 

	public boolean SWaitMultiple(String Args) throws Exception {   
 
		String[] Argz = Args.split(";");
 
		Boolean Result = false;
 
		String cwd = new File(".").getCanonicalPath();
 
		for (int i = 0; i < Argz.length; i++) {
 
			Result = true;
 
			String Path = cwd + this.Images + Argz[i];
			System.out.println("Sikuli wait: " + Path);
 
			Screen S = Sikuli.getScreen();
 
			try {
				S.wait(Path, 30);
			} catch (FindFailed e) {
				System.out.println(e.toString());
				Result = false;
			}
 
			if (Result) {
				return Result;    // true
			}
		}
 
		return Result;            // false
	}

 
2) В качестве первого параметра задается общее время ожидания картинок (скажем, 60 секунд). В течение этого времени ждем по 5 секунд каждую картинку по очереди. В случае трех картинок: ждем первую картинку 5 секунд, потом вторую 5 секунд, потом третью 5 секунд. И так 4 цикла (3*5*4=60). При нахождении любой из картинок выходим с Success.

 

	public boolean SWaitMultipleV2(String Args) throws Exception {   
 
		String[] Argz = Args.split(";");   
 
		int WaitTotal = Integer.parseInt(Argz[0]);   
 
		int NumberOfImages = Argz.length - 1;
 
		int WaitImage = 5;   // how many seconds we are going to wait each image in every iteration. 
 
		int HowMuchLoop = (int) WaitTotal/(NumberOfImages*WaitImage);
 
		Boolean Result = false;
 
		String cwd = new File(".").getCanonicalPath();
 
		System.out.println("WaitTotal: no more than " + WaitTotal + " sec.");
		System.out.println("Wait each image " + WaitImage + " sec for " + HowMuchLoop + " times.");
 
		for (int j = 0; j < HowMuchLoop; j++) {
 
			for (int i = 1; i <= NumberOfImages; i++) {  
 
				Result = true;
 
				String Path = cwd + this.Images + Argz[i];
				System.out.println("Sikuli wait: " + Path);
 
				Screen S = Sikuli.getScreen();
 
				try {
					S.wait(Path, WaitImage);
				} catch (FindFailed e) {
					System.out.println(e.toString());
					Result = false;
				}
 
				if (Result) {
					return Result;    // true
				}
			}
		}
 
		return Result;            // false
	}

Подобные обертки можно сделать и для click.

 

Запуск тестов в свернутой RDP-сессии

При запуске автотестов в свернутой RDP-сесии движок Sikuli “перестает” находить элементы графического интерфейса, поскольку при сворачивании сессии операционная система переходит в “неграфический” режим. Чтобы избежать такого перехода и работать с UI в полный рост, нужно на машине, с которой открывается RDP-сессия, добавить в ключ реестра HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client или HKEY_LOCAL_MACHINE\Software\Microsoft\Terminal Server Client DWORD-значение RemoteDesktop_SuppressWhenMinimized, равное 2 (подробности).
 
Всего доброго.

Отправить в Twitter, Facebook, FriendFeed, ВКонтакте | Опубликовано 24.07.2014 в рубрике "Автоматизация"

Комментарии (7)

  1. Автор комментария : Игорь | August 2, 2014

    Доброе время суток.
    У кого-нибудь есть положительный опыт использования sikuli в реальных проектах?
    Года два назад столкнулся с тем, что приложение очень часто падало во время прогона тестов, иногда не кликались элементы тестируемого UI, падала IDE. Больше серьезных проблем не помню, но впечатление осталось не очень хорошее. Тем более, после опыта использования божественного IBM RFT. Порадовала лишь активность разработчика (rainman, вроде) - реагировал на багрепорты со скоростью света.
    Хочу узнать у вас, коллеги, как нынче обстоят дела с sikuli? С какими проблемами сталкиваетесь в его использовании?

    [Ответить]

    Капитан отвечает:

    Игорь, добрый день.

    Опыт сугубо положительный. В реальном коммерческом проекте Sikuli используется для кликов в окне браузера, которое формируется java-апплетом. В этом окне нет привычных элементов с xpath/css locator/id и пр. Единственный способ спозиционироваться и кликнуть по элементу – это распознать изображение. IDE практически не используем, пользы от него нет. Распознавание хорошее. Помогают обертки, подобные описанным в статье. Падений нет. В случае нераспознавания (к примеру, когда действительно нет картинки) выдается исключение, которое можно обработать. Весь код на Java/Groovy.

    [Ответить]

    Anonymous отвечает:

    Положительный опыт есть. Стало удобно писать большие тесты, когда появилась возможность использовать Cucumber. С весны 2014-го в Sikuli встроена поддержка JRuby.

    [Ответить]

    Капитан отвечает:

    Добрый день. Спасибо за комментарий. А чем помог Cucumber?

    [Ответить]


  2. Автор комментария : Игорь | August 2, 2014

    Спасибо, Капитан :)

    Я пытался писать тесты на Python (фактически jython) для проекта на sciter. Возможно, собака зарыта где-то здесь.
    А давно используете? Может за эти два года стабильности в sikuli прибавилось.

    [Ответить]

    Капитан отвечает:

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

    [Ответить]

    Игорь отвечает:

    Никаких проблем с именно распознаванием у меня не было.

    Посыл понятен, вдохновили на вторую попытку. Спасибо.

    [Ответить]



Добавить комментарий

Пожалуйста, исправьте результат: дважды два равно



КРАТКОЕ СОДЕРЖАНИЕ

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


ПУТЕВОДИТЕЛЬ

Список всех статей с краткой аннотацией и разбивкой по рубрикам. Открыть карту.

ПОДПИСКА

Доступ к самым интересным материалам по электропочте и RSS. Подробности.

ИЩЕЙКА