2010-11-05 18 views
14

Estamos utilizando Selenium con la API de Java y algunas extensiones de usuario de Javascript. Usamos muchas llamadas AJAX en nuestra aplicación. Muchas de nuestras pruebas fallan aleatoriamente porque a veces las llamadas AJAX terminan más despacio que otras veces, por lo que la página no está completamente cargada. Arreglamos eso esperando elementos específicos o Thread.sleep. Estaba tratando de encontrar una manera de esperar a que terminara el tráfico de la red. Para que pudiéramos hacer esto:Selenium - Espere tráfico de red

selenium.click("some JS button"); 
selenium.waitForNetwork(); 
assertTrue(something); 

De esta manera podemos deshacernos del sueño hilo y tienen pruebas pasan más rápido cuando el servidor responde más rápido y no tener tantas pruebas fallan debido a cuestiones de tiempo.

No he podido encontrar la forma de hacer esto buscando en Google. ¿Alguien tiene alguna idea de cómo podemos lograr esto? (Preferiblemente a través de Javascript o la API de Java pero todas las sugerencias son bienvenidas).

Nota: las otras variaciones de "waitFor" no son lo que estoy buscando. Ya estamos usando esos en clics y otras cosas. Estoy buscando algo que espere el TRÁFICO DE RED. Gracias por todos los comentarios, voy a probar algunas de las sugerencias, pero todavía estoy abierto a otras ideas.

Gracias.

Respuesta

2

Actualización: Puedo usar el mismo método (wrapRequest) de la misma manera con Selenium2 y todavía funciona. La única diferencia es que no uso una extensión de usuario. Simplemente ejecuto javascript para consultar el código que carga el JSP.

Esto es lo que terminamos haciendo. (Tenga en cuenta que hay formas más fáciles de obtener si una llamada Ajax se está ejecutando si siempre está utilizando solo un marco como JQuery. Tuvimos que improvisar esto un poco más porque tenemos algunas páginas que usan JQuery y un montón que usan GWT)

Creé un archivo Javascript que cada página carga solo si está probando. (Hice esto al incluir un fragmento en la plantilla de nuestro JSP: si el parámetro querystring de prueba se pasa como verdadero, configure una cookie. Si esa cookie está configurada, incluya el archivo javascript) Este archivo javascript esencialmente envuelve el objeto XMLHttpRequest para mantener la cuenta de todas las solicitudes de envío:

function wrapRequest(xmlRequest) { 
    var oldSend = xmlRequest.prototype.send; 
    xmlRequest.prototype.send = function() { 
     var oldOnReady = this.onreadystatechange; 
     oldOnReady = function() { 
      oldOnReady.apply(this, arguments); 
      // if call is complete, decrement counter. 
     } 
     // increment counter 
     if(oldSend.apply) 
      oldSend.apply(this, arguments); 
     else if (oldOnReady.handleEvent) { //Firefox sometimes will need this 
      oldOnReady.handleEvent.apply(this, arguments); 
     } 
    } 
} 

Hay un poco más que eso si asíncrono == false, pero que debería ser bastante fácil de entender.

Luego he añadido una función para los usuarios de selenio-extensions.js que simplemente se ve así:

Selenium.prototype.getIsNetworkReady = function() { 
    if(this.browserbot.topWindow.isNetworkReady) { //sometimes this method is called before the page has loaded the isNetworkReady function 
     return this.browserbot.topWindow.isNetworkReady(); 
    } 
    return false; 
} 

También, observe el cheque en topWindow: esto es debido a que obtiene problemas cuando se selecciona un iframe.

Además, tendrá que llamar al método wrapRequest en el objeto XMLHttpRequest de cada iFrame que se cargue. Lo hago ahora mismo usando: document.addEventListener("DOMNodeInserted", onElementAdded, true); y luego en onLlementAdded. Solo tomo el iframe cuando está cargado y paso el objeto XMLHttpRequest. pero eso no funciona en IE, entonces estoy buscando una alternativa. Si alguien sabe de una mejor manera de hacerlo, así funciona tanto en IE como en FF, me encantaría escucharlo.

De todos modos, esa es la esencia de la implementación. Espero que esto ayude a cualquiera en el futuro.

0

Sí, hacer algo como esto (Pseudocódigo):

int i = 0; 
while (element is not yet present) { 
    i++; 
    if (i>TRESHOLD) { 
    throw an exception 
    } 
    Thread.sleep(200); 
} 
//go on 

Usted además probablemente quieren meterlo en una función.

4

Hay pocos tipos de esperaPara disponibles en Selenium. En su caso de prueba, si es consciente de que un texto en particular aparecerá en la carga de la página, puede usar waitForText. Si hay diferentes elementos DOM que se llenan (a través de Ajax/carga de página) puede agregar secuencialmente waitForText.

1

Ya tenemos el código del lado del cliente para cambiar el cursor del mouse durante una solicitud AJAX (usando a4j:status con los atributos onstart y onstop). Por lo tanto podemos simplemente waitFor el valor de la expresión de JavaScript

window.document.body.style.cursor 

Sin embargo, he encontrado que esto no funciona de forma fiable, es decir, a veces la prueba procede demasiado pronto. No estoy seguro de la causa, pero sospecho que la actualización del DOM no está necesariamente completa cuando se invoca onstop.

En cuanto a la reducción del retardo innecesario, puede implementar el sondeo usted mismo y sondear con más frecuencia que el selenio.

4

Después de probar todas las variantes descritas en esta página, terminamos con esta estrategia:

inyectar un javascript especial que básicamente anula todas sus métodos marco relevantes y mantener un contador de del número de solicitudes incompletas, que se incrementa al inicio y disminuye al finalizar. Debido a la naturaleza asíncrona de javascript es no suficiente para mantener una variable booleana, es probable que termine con condiciones de carrera dentro de su propia lógica.

Si está usando efectos visuales, probablemente también quiera hacer esto para efectos visuales; morphing/fading y otros elementos visuales tendrán el mismo problema.

Así que básicamente hacemos un "clic" regular y luego siempre esperamos que este contador llegue a 0 nuevamente, usando javascript como los otros sugieren aquí. Después de tener esto en su lugar, redujimos los problemas transitorios a ninguno.

Recuerde que el selenio no retorna desde el "clic" hasta que se procesen todos los eventos onclick sincrónicos, por lo que debe asegurarse de que esos contadores se incrementen como consecuencia directa de onclick.

Para obtener instrucciones sobre cómo anular los métodos de marco, debe consultar la documentación de su marco de trabajo; usamos addMethods en prototipo. Es posible mantener esta anulación en un javascript especial que solo se agrega a la página cuando se ejecutan las pruebas.

+0

Hacemos lo mismo para nuestro framework AJAX construido en casa, llamando a la función IsTheCountZeroYet() en un WaitForCondition(). Entiendo que puedes hacerlo con jQuery fácilmente. Otros marcos, tal vez también. –

+0

Lo interesante es que los contadores ajax en prototype.js tienen errores, no siempre regresan a 0.Y los efectos visuales aún no tienen este tipo de contador. Así que tuvimos que rodar el nuestro. – krosenvold

1

Esto puede no ser aceptable para usted, pero debido a los problemas similares, nos cambiamos al Selenium 2 (también conocido como WebDriver). Utilizamos PageFactory con AjaxElementLocatorFactory

Para hacer una migración más fácil, hay un Selenium Emulation y el plan es fusionar completamente Selenio 1 y WebDriver que es el objetivo principal del selenio 2.

Cuestiones relacionadas