JavaScript-Fehler in Selen erfassen


81

Gibt es eine Möglichkeit , um Erfassungsfehler auftritt , in der DOMin Seleniumund Flagge wahrscheinlich die gleichen wie ein Fehler in der Seite?

Nehmen wir als kurzes Beispiel an, ich versuche, ein Ereignis an ein nicht vorhandenes HTML-Steuerelement zu binden. Mein Browser gibt einen Fehler aus, der Folgendes besagt:

element abcd not found in the console.

Wenn ich möchte, dass derselbe Fehler meine Selentests nicht besteht und die im Browser angezeigte Meldung als Fehlermeldung angezeigt wird.

Ist es möglich so etwas zu tun?


1
Es ist jetzt 2018, gibt es eine sauberere Lösung?
Fla

Antworten:


52

Fügen Sie dieses Skript auf Ihre Seite ein und suchen Sie in Selen nach dem JSError:

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

3
Dies kann leicht erweitert werden, um auch den Fall zu erfassen, in dem JQuery nicht geladen wurde: Fügen Sie außerhalb des Onerror-Aufrufs ein $ ('body'). Attr ("JQLoaded", "Yes") hinzu. In Selen signalisiert das Vorhandensein von JSError ODER das Fehlen von JQLoaded einen Javascript-Fehler.
Nils

51
Oder Sie könnten einfach sagen, document.body.setAttribute("JSError", msg)anstatt von jQuery abhängig zu sein
Kos

3
Muss es für immer oder dynamisch zur HTML-Seite hinzugefügt werden, wenn Tests ausgeführt werden? Ich bin mir nicht sicher, ob ich Entwickler davon überzeugen würde, dieses Snippet auf jeder Seite hinzuzufügen. Vielen Dank für das Teilen von Details für mich.
Michal

3
Die verlinkte Seite ist nicht mehr verfügbar.
Chris B. Behrens

54

Ich mache das, um JavaScript-Fehler zu erfassen:

[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
Wirklich wie diese Lösung
Rob G

2
Unter Verwendung der neuesten Version von Selenium Driver 3.6.0 und Firefox 56.0 löst die Methode "GetLog" eine "Objektreferenz, die nicht auf eine Instanz eines Objekts festgelegt ist" aus, nicht sicher warum ... Dies funktionierte in einer älteren Version von WebDriver / Firefox
David Rogers

2
@ DavidRogers Ich denke, dies funktioniert nicht mehr auf Geckodriver aus diesem Grund: github.com/mozilla/geckodriver/issues/284
Christian Hujer

19

Ich bin mir nicht sicher, wann sich dies geändert hat, aber im Moment funktioniert dies für mich in Python. Die Datei ist eine einfache Seite mit einem Javascript-Fehler.

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 Version 2.48.0 Linux Firefox 43.0


Dies funktioniert auch mit webdriver.io. driver.log("browser").then(function(results){ console.log(results.value); }
Tyler Hawkins

Dies wird derzeit mit Firefox aufgrund dieses Problems nicht funktionieren: github.com/mozilla/geckodriver/issues/284
Christian Hujer

7

Hier ist die Python-Webdriver-Lösung, die ich verwende:

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 erledigt den Job.

Einmal konfiguriert, ist es eine Frage von:

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

2
Zu Ihrer Information: Dieses Projekt unterstützt derzeit nur Firefox
Ausgerichtet am

Letztes Commit vor 4 Jahren, spricht über Firefox 36 und Firebug ... Seitdem haben sich so viele Dinge geändert.
Fla

und ist das der ursprüngliche Blog-Beitrag dafür? mguillem.wordpress.com/2011/10/11/…
David


3

Ich möchte die Antwort von jhanifen wiederholen. Hier ist eine Javascript-Lösung, die nicht von jQuery abhängt. Es wird eine unsichtbare HTML-Liste am unteren Rand der Seite erstellt, die die Fehler enthält.

(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

Hier meine Lösung, inspiriert von jhanifens Antwort:

// 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

Wenn Sie Java verwenden, können Sie diese von mir eingerichtete Bibliothek ausprobieren, mit der JS-Fehler, die in einer Chromedriver-Sitzung empfangen wurden, mithilfe von Anmerkungen zu Testmethoden einfach erfasst werden können. Es funktioniert unter JUnit5 mit erweiterter Annotation und unter TestNG mit einem Listener, der die Annotation analysiert. Die Annotation enthält boolesche Werte, mit denen Sie entscheiden können, ob Sie die gefundenen Fehler nach der Testausführung bestätigen oder protokollieren möchten.

JUnit5 Beispiel:

@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

TestCase.tearDown()In meinen Python Selenium-Tests verwende ich Folgendes , wodurch der Test bei JavaScript-Fehlern fehlschlägt:

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)}')

Dies ist inspiriert von @kleptog und @ d3ming Antworten.


0

Sie versuchen, das Ereignis windows.onerror in Ihre Seite aufzunehmen, oder aktivieren das Dialogfeld Fehler anzeigen in den IE-Optionen. Wenn Sie das später in Se1 wählen, wird hängen. PS: Dies wurde hier diskutiert. Mach eine Suche.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.