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?

Baz1nga
quelle
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>
jhanifen
quelle
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));
    }
}
Magnusarinell
quelle
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

kleptog
quelle
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
d3ming
quelle
6

JSErrorCollector erledigt den Job.

Einmal konfiguriert, ist es eine Frage von:

List<JavaScriptError> jsErrorList = JavaScriptError.readErrors(driver);
Leor
quelle
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);
    };
})();
Gábor Angyal
quelle
2

Die Lösung mit "window.onerror" hat bei mir nicht funktioniert.

Daher möchte ich auf eine andere Lösung mit dem Ändern von user-extensions.js hinweisen, die mir geholfen hat:
Kann Selenium erkennen, ob die Seite JavaScript-Fehler aufweist?

Hauptvorteil: Sie müssen die Seitenquelle nicht ändern , um die Prüfung durchzuführen.

Und so verwenden Sie user-extensions.js:
Verwenden von User-Extensions mit Selenium-IDE

Hinweis: Diese Lösung funktioniert nur mit Firefox

sumid
quelle
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'}
Ali sagte OMAR
quelle
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();
}
AutomatedOwl
quelle
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.

mrts
quelle
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.

Rajasankar
quelle