Capturando el error de JavaScript en Selenium


81

¿Hay una manera de detectar errores que ocurren en el DOMen Seleniumy, probablemente, de la bandera de la misma como un error en la página?

Para dar un breve ejemplo, digamos que estoy tratando de vincular un evento en un control HTML no existente, mi navegador arroja un error que dice:

element abcd not found in the console.

Ahora, si quiero que el mismo error falle en mis pruebas de selenio y el mensaje que se muestra en el navegador se muestra como el mensaje de error.

¿Es posible hacer algo como esto?


1
Estamos en 2018 ahora, ¿hay una solución más limpia?
Fla

Respuestas:


52

Coloque este script en su página y luego verifique en Selenium el JSError:

<script type="text/javascript">
    window.onerror=function(msg){
        $("body").attr("JSError",msg);
    }
</script>

3
Esto se puede ampliar fácilmente para detectar también el caso en el que JQuery no se cargó: agregue un $ ('body'). Attr ("JQLoaded", "Yes") fuera de la llamada de error. Luego, en presencia de Selenium de JSError, O ausencia de JQLoaded, indica un error de Javascript.
Nils

51
O simplemente podría decir en document.body.setAttribute("JSError", msg)lugar de depender de jQuery
Kos

3
¿Tiene que agregarse a la página HTML para siempre o dinámicamente cuando se ejecutan las pruebas? No estoy seguro de convencer a los desarrolladores de que agreguen ese fragmento en cada página. Gracias por compartir detalles por mí.
Michal

3
La página vinculada ya no está disponible.
Chris B. Behrens

54

Estoy haciendo esto para capturar errores de JavaScript:

[TestCleanup]
public void TestCleanup()
{
    var errorStrings = new List<string> 
    { 
        "SyntaxError", 
        "EvalError", 
        "ReferenceError", 
        "RangeError", 
        "TypeError", 
        "URIError" 
    };

    var jsErrors = Driver.Manage().Logs.GetLog(LogType.Browser).Where(x => errorStrings.Any(e => x.Message.Contains(e)));

    if (jsErrors.Any())
    {
        Assert.Fail("JavaScript error(s):" + Environment.NewLine + jsErrors.Aggregate("", (s, entry) => s + entry.Message + Environment.NewLine));
    }
}

3
Realmente me gusta esta solución
Rob G

2
Usando la última versión de Selenium Driver 3.6.0 y Firefox 56.0, el método "GetLog" arroja una "Referencia de objeto no configurada para una instancia de un objeto", no estoy seguro de por qué ... Esto funcionó en una versión anterior de WebDriver / Firefox
David Rogers

2
@DavidRogers Creo que esto ya no funciona en geckodriver debido a esto: github.com/mozilla/geckodriver/issues/284
Christian Hujer

19

No estoy seguro de cuándo cambió esto, pero ahora mismo funciona para mí en Python. El archivo es una página simple con un error de JavaScript.

In [11]: driver.get("file:///tmp/a.html")

In [12]: driver.get_log("browser")
Out[12]: 
[{u'level': u'SEVERE',
  u'message': u'ReferenceError: foo is not defined',
  u'timestamp': 1450769357488,
  u'type': u''},
 {u'level': u'INFO',
  u'message': u'The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol.',
  u'timestamp': 1450769357498,
  u'type': u''}]

Python-Selenium versión 2.48.0 Linux Firefox 43.0


Esto también funciona con webdriver.io. driver.log("browser").then(function(results){ console.log(results.value); }
Tyler Hawkins

Esto no funcionará actualmente con Firefox debido a este problema: github.com/mozilla/geckodriver/issues/284
Christian Hujer

7

Aquí está la solución python webdriver que utilizo:

def check_browser_errors(driver):
    """
    Checks browser for errors, returns a list of errors
    :param driver:
    :return:
    """
    try:
        browserlogs = driver.get_log('browser')
    except (ValueError, WebDriverException) as e:
        # Some browsers does not support getting logs
        LOGGER.debug("Could not get browser logs for driver %s due to exception: %s",
                     driver, e)
        return []

    errors = []
    for entry in browserlogs:
        if entry['level'] == 'SEVERE':
            errors.append(entry)
    return errors

6

JSErrorCollector hace el trabajo.

Una vez configurado, es cuestión de:

List<JavaScriptError> jsErrorList = JavaScriptError.readErrors(driver);

2
FYI: este proyecto actualmente solo es compatible con Firefox
Alineado el

Última confirmación hace 4 años, habla de Firefox 36 y Firebug ... Tantas cosas cambiaron desde entonces.
Fla

y ¿es esta la publicación de blog original para esto? mguillem.wordpress.com/2011/10/11/…
David


3

Me gustaría repetir la respuesta de jhanifen. Aquí hay una solución de JavaScript que no depende de jQuery. Crea una lista HTML invisible en la parte inferior de la página, que contiene los errores.

(function () {
    var ul = null;
    function createErrorList() {
        ul = document.createElement('ul');
        ul.setAttribute('id', 'js_error_list');
        ul.style.display = 'none';
        document.body.appendChild(ul);
    }
    window.onerror = function(msg){
        if (ul === null)
            createErrorList();
        var li = document.createElement("li");
        li.appendChild(document.createTextNode(msg));
        ul.appendChild(li);
    };
})();


2

Aquí mi solución inspirada por la respuesta de jhanifen:

// common.js - js file common to the entire app
globalError = []
window.onerror = function (msg, url, line, col, error) {
    globalError.push({msg:msg, url:url, line:line})
};

# tests.py
def tearDown(driver):
    # assert on js error 
    ret = driver.selenium.execute_script("return globalError ")
    driver.assertFalse(ret, "errors %r " % ret)
    # ret will be a dict looking like 
    # {'line': 50, 'url': 'http://localhost:8081/static/js/common.js', 'msg': 'Uncaught ReferenceError: s is not defined'}

1

Si está usando java, puede probar esta biblioteca creada por mí que permite recopilar fácilmente los errores JS recibidos en la sesión de Chromedriver, utilizando anotaciones en los métodos de prueba. Funciona en JUnit5 con anotación extendida y en TestNG con un oyente que analiza la anotación. La anotación contiene valores booleanos que le permiten decidir si desea afirmar o registrar los errores encontrados después de la ejecución de la prueba.

Ejemplo de JUnit5:

@Test
@JSErrorsCollectorJUnit
void referenceErrorTest(TestInfo testInfo) throws InterruptedException {

    // Create a new instance of ChromeDriver.
    driver = new ChromeDriver();

    // Set your test name to point its ChromeDriver session in HashMap.
    JSErrorsDriverHolder.setDriverForTest(testInfo.getDisplayName(), driver);

    // Navigate to URL.
    driver.get("http://testjs.site88.net");

    // The click on the button in the test site should cause JS reference error.
    driver.findElement(By.name("testClickButton")).click();
    waitBeforeClosingBrowser();
}

1

Utilizo lo siguiente TestCase.tearDown()en mis pruebas de Python Selenium que hace que la prueba falle en caso de errores de JavaScript:

def tearDown(self):
    browser_logs = driver.get_log("browser")
    errors = [logentry['message'] for logentry in browser_logs if logentry['level'] == 'SEVERE']
    if errors:
        self.fail(f'The following JavaScript errors occurred: {"; ".join(errors)}')

Esto está inspirado en las respuestas de @kleptog y @ d3ming.


0

Intente incluir el evento windows.onerror en su página o habilite el cuadro de diálogo mostrar error en las opciones de IE. Si elige el más tarde en Se1 se bloqueará. PD: Esto se ha discutido aquí. Haz una búsqueda.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.