Ein gängiger Ausspruch in unserer Branche ist: „Man kann nie vorhersagen, wie ein Benutzer Ihr Produkt verwenden wird, sobald er es in den Händen hält.“ Wenn Sie jemals zugesehen haben, wie ein Stakeholder eine Website oder Webanwendung zum ersten Mal benutzt, wissen Sie das vielleicht aus eigener Erfahrung. Ich kann nicht zählen, wie oft ich gesehen habe, wie ein Benutzer scheinbar vergaß, wie er Websites auf einem Mobilgerät benutzen soll, oder versuchte, sie auf eine Weise zu benutzen, die einen denken lässt: „Aber niemand würde so etwas im echten Leben *wirklich* tun!“
Fakt ist, man weiß nie *wirklich*, was ein Benutzer im Moment tun könnte. Er könnte in einem panischen Gemütszustand sein, versuchen, etwas zu schnell zu erledigen, und tippt oder tippt nicht so, wie es ein ruhiger, konzentrierter Benutzer tun würde. Das passt gut in das allzu häufige Szenario, bei dem man für den besten Fall plant und entwickelt und nicht über Grenzfälle nachdenkt oder darüber, „was passiert, wenn die Dinge nicht perfekt in dieser Reihenfolge passieren?“ Als Entwickler neigen wir dazu, Dinge so zu bauen, dass alles verstanden wird, dass der Benutzer rational ist und einfach wissen sollte, dass schnelles Herumtippen etwas Seltsames verursachen könnte. Es kann sogar diejenigen betreffen, die versehentliche Tipp- oder Klickfehler machen, wenn sie einer App nicht volle Aufmerksamkeit schenken – wie oft haben Sie versehentlich auf einem Mobilgerät getippt, als Sie beim Gehen und Sprechen gleichzeitig versucht haben, auf einen Tweet oder eine E-Mail zu antworten.
Das Erstellen von Werkzeugen, die uns helfen, das Unvorhersehbare zu testen, ist nicht ganz neu. Im Jahr 2012 hatte Netflix seinen internen Dienst Chaos Monkey Open-Source gemacht, der „virtuelle Maschineninstanzen und Container beendet, die in Ihrer Produktionsumgebung laufen.“ Einfach ausgedrückt, ist es ein Dienst, der Server zufällig herunterschaltet, um sicherzustellen, dass ein gesamtes System bei einem Ausfall nicht heftig zusammenbricht. Unsere Entwicklungsgemeinschaften erinnern uns auch daran, nicht nur für den „Happy Path“ zu designen, sondern wie können wir unvorhergesehene Ausfallpunkte in unseren Schnittstellen erkennen, so wie wir es mit unseren Serverarchitekturen können?
Wenn hundert Affen an Schreibmaschinen die Werke von Shakespeare schreiben können, dann sollte ein Affe sicherlich Fehler und Probleme in unseren Schnittstellen finden können.
Die Affen ranlassen
Monkey Testing ist eine Testmethode, die zufällige Benutzereingaben generiert – Klicks, Wischgesten, Eingabe von Daten – mit dem alleinigen Zweck, Probleme zu finden oder Ihre Anwendung vollständig zum Absturz zu bringen. Im Gegensatz zu Unit- und Akzeptanztests, bei denen Sie Testfälle schreiben, die in einer bestimmten Reihenfolge oder unter bestimmten Bedingungen ablaufen und dadurch eine Voreingenommenheit in der Testweise Ihrer Schnittstelle erzeugen. Entwickler haben weniger Kontrolle darüber, wie ein Monkey-Test ausgeführt wird, und da er jedes Mal zufällig ausgeführt wird, testen Sie nicht nur ein Szenario, sondern eine unendliche Kombination von Interaktionen.
Obwohl diese Art von Tests für die meisten Technologie-Stacks verfügbar ist, sind webbasierte Systeme noch nicht so weit. Zum Beispiel verfügt das Android SDK über einen UI Exerciser Monkey, der die meisten Benutzeroberflächen- und Systemereignisse verarbeitet. Da Webentwickler zunehmend kritisch über Leistung und Stresstests nachdenken, sind einige dieser Ideen endlich in Form von Gremlins.js, einer JavaScript-basierten Monkey-Testing-Bibliothek des Teams von Marmelab, im Web angekommen.
Affen, Kobolde und andere lustige Viecher
Gremlins.js läuft mit so viel oder so wenig Kontrolle, wie Sie es benötigen. Die anfängliche Einrichtung ist relativ zeitsparend.
Es gibt drei Möglichkeiten, Gremlins.js zu nutzen.
Eigenständige Bibliothek
Der einfachste Weg, die Bibliothek zu integrieren, ist, sie direkt in Ihre Website einzubinden. Dadurch wird gremlins in den globalen Namensraum Ihres Projekts aufgenommen, was bedeutet, dass Sie von überall in Ihrem Projekt darauf zugreifen können.
<script src="path/to/gremlins.min.js"></script>
<script type="javascript">
// You can also run this in any file now!
gremlins.createHorde().unleash();
</script>
Require.js-Modul
Wenn Sie Require.js in Ihrem Projekt verwenden, können Sie Gremlins.js nicht-global und nach Bedarf importieren.
require.config({
paths: {
gremlins: 'scripts/libraries/gremlins.min'
}
});
require(['gremlins'], function(gremlins) {
gremlins.createHorde().unleash();
});
Lesezeichen
Wenn Sie Monkey Testing ad hoc nutzen möchten, gibt es sogar ein Lesezeichen, das ein Ein-Klick-Test auf jeder beliebigen Seite ermöglicht. Sie können das Lesezeichen unter den Installationsanweisungen herunterladen.
Rumspielen
Wenn Sie sich für die direkte Einbindung der Bibliothek oder den Import über Require entschieden haben, können Sie jetzt mit Gremlins herumspielen! In unseren Installationsbeispielen rufen wir gremlins.createHorde().unleash() auf – was macht das also?
gremlins // Yo, Gremlins
.createHorde() // Create me a default horde
.unleash(); // Then immediately release them
Sehen Sie den Pen Gremlins.js out of the box von Alicia Sedlock (@aliciasedlock) auf CodePen.
Die Standard-Horde enthält alle fünf verfügbaren Arten von zufällig generierten Benutzerinteraktionen, auch bekannt als „Gremlin-Arten“, die Folgendes umfassen:
formFillerGremlinfüllt Formulare mit Daten, klickt auf Checkboxen/Radio-Buttons und interagiert mit anderen Standard-FormularelementenclickerGremlinklickt überall auf das sichtbare DokumenttoucherGremlinberührt überall auf das sichtbare DokumentscrollerGremlinscrollt das ViewporttyperGremlinlöst zufälliges Tippen auf einer simulierten Tastatur aus
Bei der Auslösung hinterlassen Gremlins eine visuelle Anzeige auf dem Bildschirm für die ausgeführte Aktion. Sie hinterlassen auch ein Protokoll der ausgeführten Aktionen, das in der Entwicklerkonsole zu finden ist, zusammen mit zusätzlichen Daten, die mit der jeweiligen Art verbunden sind. Sie sehen dann etwa so aus wie im folgenden Beispiel.
gremlin formFiller input 5 in <input type="number" name="age">
gremlin formFiller input [email protected] in <input type="email" name="email">
gremlin clicker click at 1219 301
gremlin scroller scroll to 100 25
Standardmäßig werden Gremlins in 10-Millisekunden-Intervallen und insgesamt 1000 Mal zufällig ausgelöst.
Neben unseren „bösen“ Gremlins, die gerne Ärger machen, gibt es auch hilfreiche Gremlins, Mogwais genannt. Sie stören unsere Anwendung nicht wie Gremlins, sondern berichten hauptsächlich darüber, wie unsere Anwendung standhält, z. B. indem sie die aktuelle Bildrate protokollieren. Mogwais lösen Fehler aus, wenn die Bildrate unter 10 fällt.
mogwai fps 12.67
mogwai fps 23.56
err > mogwai fps 7.54 < err
mogwai fps 15.76
Die Kombination aus Gremlin- und Mogwai-Protokollierung liefert ein gutes Bild von allem, was während des Tests passiert ist.
Ohne viel Anpassung bietet Gremlins.js sofort eine ziemlich robuste Testsuite.
Fortgeschrittenes Herumspielen
Wenn die Standardkonfiguration nach der Verwendung nicht ausreicht, gibt es eine ganze Reihe von Möglichkeiten, die Ausführung anzupassen. Zum Beispiel möchten Sie sich vielleicht nur auf bestimmte Komponenten auf einer Seite konzentrieren, anstatt immer eine ganze Seite zu testen.
Obwohl wir nicht alle Gremlin-Arten auf bestimmte Bereiche beschränken können, können wir toucher, clicker und formFiller auf bestimmte Bereiche unserer Seite zu einem bestimmten Zeitpunkt anwenden. Insbesondere bitten wir einen Gremlin, das Elternelement eines Elements zu überprüfen, auf das er abzielt. Wenn sich dieses Element innerhalb unseres definierten Bereichs befindet, fährt der Gremlin mit der Aktion fort. Andernfalls versucht der Gremlin erneut, ein Element zum Interagieren zu finden. Wir können dem Gremlin auch mitteilen, wie oft er versuchen soll, die Aktion auszuführen, bevor er aufgibt, mit maxNbTries.
gremlins.species.clicker().canClick(function(element) {
return $(element).parents('.my-component').length;
/**
Is the element this gremlin attempted to click
within our wanted scope? Let it proceed by
returning true! Otherwise, tell it to try again
by returning false.
**/
}).maxNbTries(5); // Our gremlin will tolerate 5 false returns for canClick before it gives up and moves on
// Similarly, we can control the scope of formFiller and toucher.
gremlins.species.formFiller.canFillElement(/** do stuff here **/);
gremlins.species.toucher.canTouch(/** do stuff here **/);
Sehen Sie den Pen Gremlins.js out of the box von Alicia Sedlock (@aliciasedlock) auf CodePen.
Benutzerdefinierte Gremlins
Wenn Sie sich durch die Auswahl der verfügbaren Gremlin-Arten eingeschränkt fühlen, keine Angst! Sie können Ihre eigenen benutzerdefinierten Gremlins schreiben, um beliebige andere Aktionen auszuführen, die Sie von Benutzern erwarten. Möchten Sie zum Beispiel prüfen, was passiert, wenn ein Benutzer versucht, ein Formular zufällig an einem beliebigen Punkt seiner Erfahrung abzuschicken? Sie können hoffen, dass clicker zufällig auf unseren Submit-Button klickt, oder Sie können einen benutzerdefinierten Submission-Gremlin erstellen, um Ihre Chancen zu erhöhen und die Ausführung zu steuern.
Dies erfordert ein gewisses Verständnis dafür, wie man DOM-Ereignisse in JavaScript erstellt und anpasst. Lassen Sie uns also die Teile durchgehen, die für die Erstellung eines Submission-Gremlins notwendig sind.
gremlins.createHorde() // first, create our horde
.allGremlins() // and enable all gremlins
.gremlin(function() {
// Now let's define our submission gremlin
var targetElement, availableForms;
availableForms = document.querySelectorAll('form'); // Let's get all available form elements on the page
targetElement = availableForms[Math.floor(Math.random()*availableForms.length)]; // Then let's grab a random element from those results
// Now, we create a dummy submission event
var evt = document.createEvent('HTMLEvents'); // Create an event container
evt.initEvent('submit'); // Define our event as a submit event
targetElement.dispatchEvent(evt); // Finally, dispatch the submit event onto our randomly selected form
// We also want to make sure to log this event like others gremlins do!
console.log('gremlin submit ', targetElement);
})
.unleash();
Sehen Sie den Pen Customized gremlin with Gremlins.js von Alicia Sedlock (@aliciasedlock) auf CodePen.
Wenn Sie weitere Anleitungen zur Erstellung benutzerdefinierter Ereignisse wünschen, schauen Sie sich die Dokumentation von Mozilla Developer Network zur Erstellung von Ereignissen an und werfen Sie unbedingt einen Blick auf den Quellcode, wie Gremlins.js seine Ereignisse erstellt (der Clicker-Gremlin ist ein guter Anfang).
Horden "seeden"
Das Ausführen einer neuen Horde jedes Mal, wenn Sie diese Art von Test durchführen, hilft, Ihre Benutzeroberfläche in vielen verschiedenen Szenarien zu belasten. Wenn Sie jedoch eine Horde entfesseln und Fehler auftreten, wie sollen Sie dann wirklich wissen, ob Sie die Fehler behoben haben, die diese Fehler verursacht haben?
Für Fälle, in denen Sie dieselbe Horde mehrmals ausführen möchten, können Sie die Horde "seeden". Dies gibt Ihnen jedes Mal, wenn Sie den Test ausführen, genau dieselbe Horde.
var horde = gremlins.createHorde();
horde.seed(1234);
horde.unleash();
Sie sollten abwägen, wie oft Sie geseedete Horden im Vergleich zu zufälligen Horden in einer langfristigen Lösung verwenden. Während geseedete Horden Wiederholtests ermöglichen, liegt ein großer Teil des Nutzens von Monkey Testing in seiner Zufälligkeit, die in einem Szenario, in dem immer derselbe Seed verwendet wird, etwas müßig wird.
Fazit
Die Web-Community spricht oft davon, keine Annahmen über unsere Benutzer zu treffen. Sie haben möglicherweise langsame Verbindungen, kein ganz aktuelles Gerät oder sind auf eine Weise beeinträchtigt, die die von ihnen verwendete Website zugänglich machen muss. Wir können auch nicht versprechen, dass die fünfjährige Jaime nicht das Telefon ihrer Eltern schnappt, wild zu tippen beginnt und erhebliche Probleme mit dem, was sie gerade benutzt, verursacht. Oder Kassidy aus dem Marketing, die nach den ersten Händen am Produkt aufgeregt oder in Aufregung tippt. Die Reihenfolge, Geschwindigkeit oder Wiederholung einer Benutzeraktion kann nicht vorhergesagt werden. Als Entwickler sind wir unseren Benutzern schuldig, sicherzustellen, dass unsere Dienste nicht unerwartet kaputt gehen, nur weil wir davon ausgehen, dass sie nur "Happy Path"-Aktionen ausführen.
Die Auswahlmöglichkeiten für clientseitiges Monkey Testing sind begrenzt, aber Gremlins.js beherrscht die Grundlagen von Anfang an. Wie bei jeder Art von Testbibliothek oder Framework können wir sie nur verbessern, wenn Leute sie benutzen! Sie suchen aktiv nach Mitwirkenden. Wenn Sie also eine Wunschliste mit Dingen haben, die diese Bibliothek tun kann, lassen Sie es sie wissen!
Das Pen mit Focus-Komponenten und Gremlin.js versaut Chrome 54 und lässt mich nicht mehr auf der Seite nach unten scrollen. Sehen das noch andere Benutzer in einem anderen Browser?
Es fokussiert buchstäblich Dinge, wie es soll, was den Browser dazu bringt, dieses Element in die Ansicht zu bringen. Wenn Sie alles gesehen haben, was Sie in der Demo sehen mussten, können Sie den Ergebnis-Tab schließen.
Hey Leute,
Entschuldigen Sie meine Unwissenheit, aber wie stellen die Gremlins fest, dass sie etwas kaputt gemacht haben (wie das Layout einer Seite oder eines Widgets)? Abgesehen vom Beobachten der FPS...
Hallo! Keine Entschuldigung nötig. :)
Abgesehen von FPS sind Mogwais für das Abfangen aller JavaScript-Fehler zuständig. In dieser Bibliothek werden
console.errorundwindow.onerrorüberschrieben und fangen alle codespezifischen Fehler ab (denken Sie an Fehler wie'undefined is not a function'oder'could not find x of undefined').Dies wird von einem sehr spezifischen Mogwai namens Gizmo gehandhabt. Sie können sich den Quellcode von Gizmo ansehen und einen Blick auf die internen Arbeitsweisen werfen, wenn Sie interessiert sind! Ich hoffe, das hat etwas mehr Klarheit gebracht. https://github.com/marmelab/gremlins.js/blob/master/src/mogwais/gizmo.js
Das ist genial! Danke an alle, dass sie das ans Licht gebracht haben! Ich kann es kaum erwarten, das zu meiner Bibliothek hinzuzufügen!
Prost!
J
PS. Gibt es eine Möglichkeit, die Methode "createHorde()" in "addWater()" umzubenennen?
[Haftungsausschluss: Ich habe den Artikel nur überflogen.] Gibt es eine Möglichkeit, den Seed jeder zufälligen Horde zu protokollieren, sodass, wenn eine bestimmte Horde einen Fehler verursacht, Sie diese spezifische Horde mehrmals wiederholen können, während Sie an einer Korrektur arbeiten?
Hallo Nathan! Das war etwas, das mich selbst interessiert hat. Es ist etwas komplizierter, als nur den aktuellen Seed zu ermitteln.
Wenn Sie eine Horde haben, können Sie über
horde._randomizerauf ihre Zufallsdaten zugreifen. Dies wird mit einer anderen Bibliothek namens Chance.js generiert, die alle Zufallsberechnungen durchführt. Beim Durchsuchen dieses Objekts scheint es mir zumindest so, dass sie selbst keinen spezifischen Seed dafür speichern, wie sie die Daten generiert haben. Vielleicht fehlt mir aber auch etwas!Ich entwickle seit über zehn Jahren Softwareanwendungen und habe noch nie von Monkey Testing gehört. Wie unterscheidet es sich von dem, was tatsächlich beschrieben wird: Chaos Testing?
Hallo Josh! Meiner Erfahrung nach werden Chaos Testing und Monkey Testing (und auch Fuzz Testing) oft austauschbar verwendet, obwohl sie sich in ihren Feinheiten leicht unterscheiden. Chaos Testing befasst sich eher mit dem absichtlichen zufälligen Verursachen von Fehlern, während Monkey Testing eher mit dem Ausführen zufälliger Aktionen zu tun hat, die *möglicherweise*, aber nicht immer, zu Fehlern führen. Beide haben zufällige Elemente und basieren beide definitiv auf dem Testen der Widerstandsfähigkeit dessen, was auch immer Sie bauen, aber sie haben unterschiedliche Absichten dahinter.
Gibt es eine Möglichkeit, zufällige Horden zu verwenden, die Seeds nur dann speichern, wenn ein Fehler abgefangen wird? Dadurch werden jedes Mal zufällige Szenarien verwendet, aber mit der Möglichkeit, Fehler nach der Anwendung einer Korrektur erneut abzuspielen?
Danke, dass Sie diese Bibliothek hervorgehoben haben. Sehr nützlich.
In Ihrem Abschnitt über benutzerdefinierte Gremlins wollte ich nur darauf hinweisen, dass Event.initEvent() veraltet ist und in meinem Firefox FF45.3 nicht funktioniert, daher muss der folgende Code ersetzt werden.
Da es veraltet ist, verwenden Sie initEvent() nicht mehr. Verwenden Sie stattdessen einen spezifischen Event-Konstruktor wie Event().
Danke! Tolle Sache.
Es wäre interessant, einige Fallstudien mit Beispielen zu sehen, bei denen jemand einen Fehler gefunden hat, weil er Monkey Testing mit gremlins.js durchgeführt hat.