05 сентября 2012

Selenium: Определение IP адреса ноды на которой выполняется тест


Терминология 


  1. грид - Selenium Grid - состоит из хаба и нод.
  2. хаб (Selenium Grid Hub) - экземпляр selenium-server-standalone запущенный с ключом "-role hub"
  3. нода (Selenium Grid node) - экземпляр selenium-server-standalone запущенный с ключом "-role node -hub http://<адрес хаба>:4444/grid\register"


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

Дальнейшее рассмотрение проблемы привело меня к следующbv вариантам решения:

  1. дописать свой собственный сервлет к кодобазe Selenium
  2. написать нечто внешнее что позволило бы определять IP адерса нод и отдаавать их.


Первый варинат решения является наиболее элегантным и рассово-правильным, если не принимать в вонимание то, что за 1(!) год работы над Selenium 2 было выпущено только 25(!!!) релизов.
Если вам нужно постоянно зхапускать тесты на последней версии браузера, то с выходом каждой новой версии вам придется сливать код из mainline Selenium-а, мерджить его со своей версией проекта, пересобирать, и раскатывать по своему гриду.
Ну и как бесплатный бонус  - шанс что-то сломать и потом долго это искать.

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

Ну и пример приложения.
Точка входа

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
 
public class Runner {
 
 public static void main(String[] args) throws Exception {
  Server server = new Server(9090);
  final ServletContextHandler servletContextHandler = new ServletContextHandler();
  servletContextHandler.addServlet(new ServletHolder(new IpDetectorServlet()), "/getIp");
  server.setHandler(servletContextHandler);
  server.start();
  server.join();
 }
}
 

Ну и начинка которая непосредственно занимается определением и возвратом IP

import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class IpDetectorServlet extends HttpServlet {
 
 /**
  * 
  */
 private static final long serialVersionUID = 5661514303101772232L;
 
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  final String remoteAddr = request.getRemoteAddr();
  response.setContentType("text/plain");
  response.setContentLength(remoteAddr.length());
  response.getWriter().write(remoteAddr);
 }
 
 
}


Дальше упаковываем все это в стандартный jar и можем запускать на любоей платформе.
Чтобы получить адрес ноды на которой выполняется тест теперь нужно в коде теста просто иметь вот такую строчку

driver.get("http:10.10.10.12:9090/getIp");
String ip = driver.findElement(By.tagName("body")).getText(); // так конечно делать не хорошо :)
System.out.println(ip);


Исходники на GitHub 

PS очень надеюсь, что в ближайшее время разработчики Selenium сделают HUB API и потребность в подобного рода "велосипедах" отпадет.