Chromedriver и паразитный перехват фокуса на окно

Вводная:

  • Win7x64
  • WebDriver 3.11.0
  • Chromedriver 2.38
  • Java 8

Поднят микросервис в качестве динамического балансира и сервера инстансов.
Запускается N-экземпляров браузеров(FF,Ch). Запускаются пакеты тестов. Через микросервис рабочие задачи распределяются по инстансам.

Если в работе задействованы браузеры FF, тогда проблем нет никаких абсолютно.
Если в работе задействованы браузеры Ch, тогда время от времени каждый инстанс производит перехват фокуса на себя. Т.е. фактически становится активным какое-либо (из инстансов) “окно” ОС. Бесит неимоверно, мешает нормальной мультипроцессной много-поточной асинхронной работе (бывало, что за фокус начинали “драться” сразу несколько окон). Куда копать и как это лечить?

Гуглить я конечно пытался, но ничего нужного найти не удалось… может рукожоп и кто-то подскажет правильную поисковую выдачу?

UPD 1: Дома стоит Win10x64, однако проблема аналогичная - думаю, что от ОС не зависит (конечно, могу ошибаться).
UPD 2: Перехват фокуса наблюдал еще год назад, но тогда такой подсистемы из балансировщика и сервера готовых не имел (только разрабатывалось) - тесты не гонялись с таким параллелизмом. Не шибко мешало.

Любители велосипедов плачут, но продолжают резаться о свои педальки…

Есть же готовое решение - Selenoid, решает все перечисленные проблемы с блеском.

2 лайка

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

Что ж тут неконструктивного? Я же предлагаю решение. Я знаю ровно о тех проблемах, которые вы описали, и их селеноид решит.

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

2 лайка

Да, я понимаю, что Docker позволяет много хорошего. И это для своих задач весьма хороший тулл. Согласен.
Однако надо понимать, что тут нет ситуации “выбираем что использовать”, но есть ситуация “есть проблема, нужно её решение”. Без применения лекарств вида “гильотина, если болит голова”.

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

На Stackoverflow я уже нашел людей со схожей проблемой о перехвате фокуса окнами Chrome. Толкового решения там не нашли. Вроде как баг chromedriver, ибо так быть не должно.
В версии 2.28 еще работало нормально. Поломали в 2.29. Но к старой версии драйвер даунгрейдить не вариант - там не было хотя бы урезанной поддержки W3CHttpCommandCodec, которая так же нам крайне необходима.

Никак не могу понять - что необходимо “починить”/“переписать” в самой реализации chromedriver.

Вы уверены что проблема в драйвере, а не в браузере? Локализовать пытались?

Простите, немного не уверен, что вы подразумеваете под “локализовать пытались”?
Разные версии ОС пробовал. Разные браузеры пробовал. Проблема стабильно только при использовании Chrome (через, естественно, chromedriver).
Чисто в теории надо проверить мнение со Stackoverflow и сделать тестовый тест на древней версии драйвера. Этого я еще не делал. Однако на последних билдах (начиная со 2.32) эта проблема встречается постоянно.

Заменить [quote]время от времени[/quote] на конкретные степы.

Да, вы оказались прозорливы - нашел несколько точек, в следствии которых происходит неполадка.
Это редирект и клик. Однако у них есть общий нюанс:

ExecutorService executor    = Executors.newSingleThreadExecutor();
Future<String> future       = executor.submit(new LoopTimeClick(timeLimit,element));

Вот такая конструкция есть. Однако я в недоумении - если делать совсем без оберток редиректы и клики, тогда проблема не возникает. Но что не так с этой оберткой? Она же есть и при использовании FF, однако там такой проблемы нет. :frowning:

Сложно дебажить через форум.

1 лайк

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

1 лайк

А headless режим chrom’а не пробовали? Там фокус не перехватывается, но работает он немного иначе.

1 лайк

Просто не работайте работу на машине на которой бегут браузеры. Запустите отдельный тазик\виртуалку\клауд инстанс и цельте ваши тесты в него.

В любом случае какой бы вы велосипед не придумали - овчинка выделки не стоит. Я вообще предпочитаю даже мышку и клавиатуру не трогать пока бегут тесты.

1 лайк

Пардон за запоздалый ответ. Однако быть может кому-либо он нервов спасет таки…
Данный баг является результатом редкого стечения обстоятельств:

  • если вы используете “сторонний” инстанс браузера…
  • и при этом переписываете сегмент веб-драйвера
@Override
public Response execute(Command command) throws IOException {
	Response response;
	if (Objects.equals(command.getName(), "newSession")) {
		response = new Response();
		response.setSessionId(sessionId.toString());
		response.setStatus(0);
		response.setValue(Collections.<String, String>emptyMap());

		try {
			Field commandCodec;
			Field responseCodec;

			commandCodec    = this.getClass().getSuperclass().getDeclaredField("commandCodec");
			commandCodec.setAccessible(true);
			switch (browser) {
				case "firefox": commandCodec.set(this, new W3CHttpCommandCodec());
					break;
				default: commandCodec.set(this, new JsonHttpCommandCodec());
					break;
			}


			responseCodec   = this.getClass().getSuperclass().getDeclaredField("responseCodec");
			responseCodec.setAccessible(true);
			switch (browser) {
				case "firefox": responseCodec.set(this, new W3CHttpResponseCodec());
					break;
				default: responseCodec.set(this, new JsonHttpResponseCodec());
					break;
			}

		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

	} else {
		response = super.execute(command);
	}
	return response;
}

- а так же используете асинхронные потоки

ExecutorService executor    = Executors.newSingleThreadExecutor();
Future<Void> future         = executor.submit(new LoopTimeRedirect(timeLimit,url,TME));

class LoopTimeRedirect implements Callable<Void> {
	LoopTimeRedirect(...) {
		...	
	}
	@Override
	public Void call() throws Exception {
		//logic here
		return null;
	}
}

В таком случае проблема возникнет при срабатывании колбека из Callable в основной поток из-за проблемы в
JsonHttpResponseCodec/JsonHttpCommandCodec - FF использует новый вариант (W3C) с улучшенными возможностями. Багтрекер Chrome сообщил, что они аналогично произведут миграцию на W3C кодек и будут поддерживать данные технологические приемы.