Im letzten Artikel habe ich über einige Ideen und Muster wie das Page Object-Muster gesprochen, die helfen, wartungsfähige UI-Tests zu schreiben. In diesem Artikel werden einige fortgeschrittene Themen behandelt, die Ihnen beim Schreiben robusterer Tests helfen und bei Problemen Fehler beheben können:
Ich werde Selenium für die in diesem Artikel behandelten Themen zur Browser-Automatisierung verwenden.
Ähnlich wie im vorherigen Artikel sind die in diesem Artikel behandelten Konzepte und Lösungen unabhängig von der verwendeten Sprache und dem UI-Framework anwendbar. Bevor Sie fortfahren, lesen Sie bitte den vorherigen Artikel, da ich einige Male auf ihn und seinen Beispielcode verweisen werde. Mach dir keine Sorgen; Ich warte hier.
Hinzufügen Thread.Sleep
(oder generell Verzögerungen) fühlt sich beim UI-Testen wie ein unvermeidlicher Hack an. Sie haben einen Test, der zeitweilig fehlschlägt, und nach einigen Nachforschungen führen Sie diesen auf gelegentliche Verzögerungen in der Antwort zurück. Beispielsweise navigieren Sie zu einer Seite und suchen oder bestätigen etwas, bevor die Seite vollständig geladen ist und Ihr Browser-Automatisierungs-Framework eine Ausnahme ausweist, die besagt, dass das Element nicht vorhanden ist. Viele Dinge könnten zu dieser Verzögerung beitragen. Zum Beispiel:
Oder eine Mischung aus diesen und anderen Themen.
Nehmen wir an, Sie haben eine Seite, die normalerweise weniger als eine Sekunde benötigt, um zu laden, aber die Tests, die sie schlagen, schlagen gelegentlich ab, weil die Antwort gelegentlich verzögert wird. Sie haben einige Möglichkeiten:
Sie sehen, es gibt keinen Gewinn mit willkürlichen Verzögerungen: Sie erhalten entweder eine langsame oder eine brüchige Testsuite. Hier zeige ich Ihnen, wie Sie vermeiden, feste Verzögerungen in Ihre Tests einzufügen. Wir werden zwei Arten von Verzögerungen besprechen, die so ziemlich alle Fälle abdecken sollten, mit denen Sie sich befassen müssen: Fügen Sie eine globale Verzögerung hinzu und warten Sie, bis etwas passiert.
Wenn alle Ihre Seiten ungefähr dieselbe Zeit zum Laden benötigen, was länger als erwartet ist, werden die meisten Tests aufgrund einer unzeitigen Reaktion fehlschlagen. In solchen Fällen können Sie implizite Wartezeiten verwenden:
Ein implizites Warten ist, WebDriver anzuweisen, das DOM für eine bestimmte Zeit abzufragen, wenn versucht wird, ein Element oder Elemente zu finden, wenn diese nicht sofort verfügbar sind. Die Standardeinstellung ist 0. Nach der Festlegung wird die implizite Wartezeit auf die Lebensdauer der WebDriver-Objektinstanz festgelegt.
So legen Sie eine implizite Wartezeit fest:
WebDriver-Treiber = neuer FirefoxDriver (); driver.Manage (). Timeouts (). Implicitly Warten (TimeSpan.FromSeconds (5));
Auf diese Weise sagen Sie Selenium, dass es bis zu 5 Sekunden warten soll, wenn es versucht, ein Element zu finden oder mit der Seite zu interagieren. So können Sie jetzt schreiben:
driver.Url = "http: // somedomain / url_that_delays_loading"; IWebElement myDynamicElement = driver.FindElement (By.Id ("someDynamicElement"));
anstatt:
driver.Url = "http: // somedomain / url_that_delays_loading"; Thread.Sleep (5000); IWebElement myDynamicElement = driver.FindElement (By.Id ("someDynamicElement"));
Der Vorteil dieses Ansatzes ist das FindElement
kehrt zurück, sobald das Element gefunden wird, und wartet nicht die gesamten 5 Sekunden, wenn das Element früher verfügbar ist.
Sobald das implizite Warten auf Ihr festgelegt ist WebDriver
Es gilt beispielsweise für alle Aktionen am Fahrer. so können Sie viele loswerden Thread.Sleep
s in Ihrem Code.
5 Sekunden ist eine Wartezeit, die ich für diesen Artikel aufgespart habe - Sie sollten die optimale implizite Wartezeit für Ihre Anwendung finden und diese Wartezeit so kurz wie möglich machen. Aus den API-Dokumentationen:
Die Erhöhung des impliziten Wartezeitlimits sollte vernünftig verwendet werden, da dies die Testlaufzeit negativ beeinflusst, insbesondere bei langsameren Standortstrategien wie XPath.
Selbst wenn Sie XPath nicht verwenden, verlangsamt das Verwenden langer impliziter Wartezeiten die Tests, insbesondere wenn einige Tests tatsächlich fehlschlagen, da der Webtreiber lange warten wird, bevor das Zeitlimit überschritten wird und eine Ausnahme ausgelöst wird.
Das implizite Warten ist eine großartige Möglichkeit, viele hart codierte Verzögerungen in Ihrem Code zu beseitigen. Sie werden sich jedoch immer noch in einer Situation befinden, in der Sie einige feste Verzögerungen in Ihrem Code hinzufügen müssen, da Sie darauf warten, dass etwas passiert: Eine Seite ist langsamer als alle anderen Seiten und Sie müssen länger warten Warten auf das Ende eines AJAX-Aufrufs oder auf das Erscheinen oder Verschwinden eines Elements von der Seite usw. Hier müssen Sie explizit warten.
Sie haben also die implizite Wartezeit auf 5 Sekunden festgelegt und es funktioniert für viele Ihrer Tests. Es gibt jedoch immer noch ein paar Seiten, die manchmal länger als 5 Sekunden dauern und zu fehlgeschlagenen Tests führen.
Als Randbemerkung sollten Sie untersuchen, warum eine Seite zuerst so lange dauert, bevor Sie versuchen, den fehlerhaften Test zu reparieren, indem Sie ihn länger warten lassen. Auf der Seite liegt möglicherweise ein Leistungsproblem vor, das zum roten Test führt. In diesem Fall sollten Sie die Seite korrigieren, nicht den Test.
Im Falle einer langsamen Seite können Sie feste Verzögerungen durch explizite Wartezeiten ersetzen:
Ein explizites Warten ist ein Code, den Sie definieren, um auf das Auftreten einer bestimmten Bedingung zu warten, bevor Sie im Code fortfahren.
Sie können explizite Wartezeiten mit anwenden WebDriverWait
Klasse. WebDriverWait
lebt in WebDriver.Support
Montage und kann mit Selenium.Support Nuget installiert werden:
////// Bietet die Möglichkeit, während der Testausführung auf eine beliebige Bedingung zu warten. /// öffentliche Klasse WebDriverWait: DefaultWait/// /// Initialisiert eine neue Instanz von /// Die WebDriver-Instanz hat gewartet.Der Timeout-Wert, der angibt, wie lange auf die Bedingung gewartet werden soll. public WebDriverWait (IWebDriver-Treiber, TimeSpan-Zeitlimit); ///Klasse. /// /// Initialisiert eine neue Instanz von /// Ein Objekt, das das implementiertKlasse. /// Schnittstelle, um festzustellen, wann die Zeit vergangen ist.Die WebDriver-Instanz hat gewartet.Der Timeout-Wert, der angibt, wie lange auf die Bedingung gewartet werden soll.EIN Wert, der angibt, wie oft geprüft werden soll, ob die Bedingung wahr ist. public WebDriverWait (IClock-Uhr, IWebDriver-Treiber, TimeSpan-Zeitlimit, TimeSpan sleepInterval);
Hier ist ein Beispiel, wie Sie verwenden können WebDriverWait
in deinen Tests:
driver.Url = "http: // somedomain / url_that_takes_a_long_time_to_load_de"; WebDriverWait wait = new WebDriverWait (Treiber, TimeSpan.FromSeconds (10)); var myDynamicElement = wait.Until (d => d.FindElement (By.Id ("someElement")));
Wir sagen Selenium, dass wir wollen, dass es bis zu 10 Sekunden auf diese bestimmte Seite / dieses Element wartet.
Sie werden wahrscheinlich ein paar Seiten haben, die länger dauern als die implizite Standardwartezeit. Es ist keine gute Kodierungsmethode, wenn Sie diesen Code überall wiederholen. Letztendlich Testcode ist Code. Sie können dies stattdessen in eine Methode extrahieren und aus Ihren Tests verwenden:
public IWebElement FindElementWithWait (By by, int secondsToWait = 10) var wait = new WebDriverWait (WebDriver, TimeSpan.FromSeconds (secondsToWait)); return wait.Until (d => d.FindElement (by));
Dann können Sie diese Methode verwenden als:
var slowPage = new SlowPage ("http: // somedomain / url_that_takes_a_long_time_to_load"); var element = slowPage.FindElementWithWait (By.Id ("someElement"));
In diesem Beispiel wird gezeigt, wie die Methode möglicherweise aussehen könnte und wie sie verwendet werden könnte. Idealerweise würden Sie alle Seiteninteraktionen auf Ihre Seitenobjekte verschieben.
Sehen wir uns ein weiteres Beispiel für ein explizites Warten an. Manchmal ist die Seite vollständig geladen, aber das Element ist noch nicht vorhanden, da es später als Ergebnis einer AJAX-Anforderung geladen wird. Vielleicht ist es kein Element, auf das Sie warten, Sie möchten nur warten, bis eine AJAX-Interaktion beendet ist, bevor Sie eine Assertion machen können, z. B. in der Datenbank. Auch hier verwenden die meisten Entwickler Thread.Sleep
B. sicherstellen, dass der AJAX-Aufruf abgeschlossen ist und sich der Datensatz jetzt in der Datenbank befindet, bevor er zur nächsten Zeile des Tests übergeht. Dies kann durch JavaScript-Ausführung leicht korrigiert werden!
Bei den meisten Browser-Automatisierungsframeworks können Sie JavaScript in der aktiven Sitzung ausführen. Selenium bildet dabei keine Ausnahme. In Selenium gibt es eine Schnittstelle namens IJavaScriptExecutor
mit zwei Methoden:
////// Definiert die Schnittstelle, über die der Benutzer JavaScript ausführen kann. /// öffentliche Schnittstelle IJavaScriptExecutor ////// Führt JavaScript im Kontext des aktuell ausgewählten Frames oder Fensters aus. /// /// Der auszuführende JavaScript-Code. ////// Der vom Skript zurückgegebene Wert. /// object ExecuteScript (Zeichenkettenskript, params object [] args); ////// Führt JavaScript asynchron im Kontext des aktuell ausgewählten Frames oder Fensters aus. /// /// Der auszuführende JavaScript-Code. ////// Der vom Skript zurückgegebene Wert. /// object ExecuteAsyncScript (Zeichenfolgen-Skript, params object [] args);
Diese Schnittstelle wird von implementiert RemoteWebDriver
Dies ist die Basisklasse für alle Webtreiberimplementierungen. Sie können also über Ihre Webtreiberinstanz anrufen ExecuteScript
ein JavaScript-Skript ausführen. Mit dieser Methode können Sie warten, bis alle AJAX-Aufrufe beendet sind (vorausgesetzt, Sie verwenden jQuery):
// Es wird davon ausgegangen, dass es sich in einer Klasse befindet, die über das Feld / die Eigenschaft 'WebDriver' auf die aktive Instanz 'WebDriver' zugreifen kann. public void WaitForAjax (int secondsToWait = 10) var wait = new WebDriverWait (WebDriver, TimeSpan.FromSeconds (secondsToWait)); wait.Until (d => (bool) ((IJavaScriptExecutor) d) .ExecuteScript ("return jQuery.active == 0"));
Kombiniere das ExecuteScript
mit WebDriverWait
und du kannst loswerden Thread.Sleep
für AJAX-Aufrufe hinzugefügt.
jQuery.active
gibt die Anzahl der aktiven AJAX-Aufrufe zurück initiiert von jQuery; Wenn es also null ist, werden keine AJAX-Aufrufe ausgeführt. Diese Methode funktioniert offensichtlich nur, wenn alle AJAX-Anforderungen von jQuery initiiert werden. Wenn Sie andere JavaScript-Bibliotheken für die AJAX-Kommunikation verwenden, sollten Sie die entsprechenden API-Dokumentationen nach einer gleichwertigen Methode durchsuchen oder AJAX-Aufrufe selbst verfolgen.
Mit explizitem Warten können Sie eine Bedingung festlegen und warten, bis sie erfüllt ist oder das Zeitlimit abläuft. Wir haben gesehen, wie wir prüfen können, ob AJAX-Aufrufe beendet werden sollen. Ein anderes Beispiel ist die Sichtbarkeit eines Elements. Genau wie bei der AJAX-Prüfung können Sie eine Bedingung schreiben, die die Sichtbarkeit eines Elements überprüft. Dafür gibt es eine einfachere Lösung Erwartete Bedingung
.
Aus der Dokumentation von Selen:
Bei der Automatisierung von Webbrowsern treten häufig einige Bedingungen auf.
Wenn Sie Java verwenden, haben Sie Glück Erwartete Bedingung
Klasse in Java ist ziemlich umfangreich und hat viele Bequemlichkeitsmethoden. Die Dokumentation finden Sie hier.
.Netzentwickler sind nicht ganz so glücklich. Es gibt noch eine Erwartete Bedingungen
Klasse in WebDriver.Support
Montage (hier dokumentiert), aber es ist sehr minimal:
öffentliche versiegelte Klasse ExpectedConditions ////// Erwartung für die Überprüfung des Titels einer Seite. /// /// Der erwartete Titel, der exakt übereinstimmen muss. ////// öffentliche statische Funktionwenn der Titel übereinstimmt; Andernfalls, . /// TitleIs (String-Titel); /// /// Eine Erwartung zur Überprüfung, ob der Titel einer Seite eine Groß- / Kleinschreibung enthält. /// /// Das Fragment des Titels erwartet. ////// öffentliche statische Funktionwenn der Titel übereinstimmt; Andernfalls, . /// TitleContains (Zeichenfolgentitel); /// /// Erwartung, ob ein Element im DOM einer /// Seite vorhanden ist. Dies bedeutet nicht notwendigerweise, dass das Element sichtbar ist. /// /// Der Locator, mit dem das Element gesucht wurde. ////// Das öffentliche statische FunktionSobald es lokalisiert ist. /// ElementExists (Nach Locator); /// /// Eine Erwartung zur Überprüfung, ob ein Element im DOM einer Seite /// vorhanden und sichtbar ist. Sichtbarkeit bedeutet, dass das Element nicht nur angezeigt wird, sondern /// auch eine Höhe und Breite hat, die größer als 0 ist. /// /// Der Locator, mit dem das Element gesucht wurde. ////// Das öffentliche statische FunktionSobald es lokalisiert und sichtbar ist. /// ElementIsVisible (nach Locator);
Sie können diese Klasse in Kombination mit verwenden WebDriverWait
:
var wait = new WebDriverWait (Treiber, TimeSpan.FromSeconds (3)) var Element = wait.Until (ExpectedConditions.ElementExists (By.Id ("foo")));
Wie Sie anhand der Klassensignatur oben sehen können, können Sie anhand von den Titel oder Teile davon sowie das Vorhandensein und die Sichtbarkeit von Elementen überprüfen Erwartete Bedingung
. Die sofortige Unterstützung in .Net ist möglicherweise sehr gering. Aber diese Klasse ist nichts weiter als ein Wrapper für einige einfache Bedingungen. Sie können andere übliche Bedingungen in einer Klasse genauso einfach implementieren und mit verwenden WebDriverWait
aus Ihren Testskripten.
Ein weiteres Juwel nur für Java-Entwickler ist FluentWait
. Von der Dokumentationsseite, FluentWait
ist
Eine Implementierung der Wait-Schnittstelle, bei der das Zeitlimit und das Abfrageintervall im laufenden Betrieb konfiguriert werden können. Jede FluentWait-Instanz definiert die maximale Wartezeit auf eine Bedingung sowie die Häufigkeit, mit der die Bedingung überprüft werden soll. Darüber hinaus kann der Benutzer das Warten so konfigurieren, dass bestimmte Arten von Ausnahmen während des Wartens ignoriert werden, z. B. NoSuchElementExceptions bei der Suche nach einem Element auf der Seite.
Im folgenden Beispiel versuchen wir, ein Element mit der ID zu finden foo
auf der Seite alle fünf Sekunden bis zu 30 Sekunden abrufbar:
// Warten Sie 30 Sekunden, bis ein Element auf der Seite vorhanden ist, und prüfen Sie // alle fünf Sekunden, ob es vorhanden ist. Wartenwait = neues FluentWait (Treiber) .withTimeout (30, SECONDS) .pollingEvery (5, SECONDS) .ignoring (NoSuchElementException.class); WebElement foo = wait.until (neue Funktion () public WebElement apply (WebDriver-Treiber) return driver.findElement (By.id ("foo")); );
Es gibt zwei herausragende Dinge über FluentWait
: Zum einen können Sie das Abrufintervall angeben, das die Testleistung verbessern könnte, zum anderen können Sie die Ausnahmen ignorieren, an denen Sie nicht interessiert sind.
FluentWait
ist ziemlich großartig und es wäre cool, wenn es auch in .Net ein Äquivalent gäbe. Das heißt, es ist nicht so schwer, es mit zu implementieren WebDriverWait
.
Sie haben Ihre Seitenobjekte eingerichtet, haben einen schönen DRY-wartbaren Testcode und vermeiden feste Verzögerungen bei Ihren Tests. aber Ihre Tests schlagen immer noch fehl!
Die Benutzeroberfläche ist normalerweise der am häufigsten geänderte Teil einer typischen Anwendung: Manchmal verschieben Sie Elemente auf einer Seite, um das Design der Seite zu ändern, und manchmal ändert sich die Seitenstruktur entsprechend den Anforderungen. Diese Änderungen am Seitenlayout und -design können zu einer Vielzahl von Tests führen, wenn Sie Ihre Selektoren nicht sinnvoll auswählen.
Verwenden Sie keine Fuzzy-Selektoren und verlassen Sie sich nicht auf die Struktur Ihrer Seite.
Oft wurde ich gefragt, ob es in Ordnung ist, den Elementen auf der Seite nur zum Testen eine ID hinzuzufügen, und die Antwort ist ein klares Ja. Um unsere Code Unit testbar zu machen, nehmen wir viele Änderungen vor, z. B. das Hinzufügen von Schnittstellen und die Verwendung von Dependency Injection. Testcode ist Code. Tun Sie, was Sie brauchen, um Ihre Tests zu unterstützen.
Nehmen wir an, wir haben eine Seite mit der folgenden Liste:
In einem meiner Tests möchte ich auf das Album "Let There Be Rock" klicken. Ich würde um Ärger bitten, wenn ich den folgenden Selektor verwenden würde:
By.XPath ("// ul [@ id = 'album-list'] / li [3] / a")
Wenn möglich, sollten Sie den Elementen eine ID hinzufügen und sie direkt anvisieren, ohne sich auf die umgebenden Elemente zu verlassen. Ich werde also eine kleine Änderung an der Liste vornehmen:
Ich habe hinzugefügt Ich würde
Attribute zu Ankern basierend auf der ID der eindeutigen Alben, sodass wir einen Link direkt anvisieren können, ohne durchgehen zu müssen ul
und li
Elemente. So kann ich jetzt den spröden Selektor mit ersetzen Von.Id ("album-35")
was garantiert funktioniert, solange das Album auf der Seite ist, was übrigens auch eine gute Behauptung ist. Um diesen Selektor zu erstellen, müsste ich natürlich über den Testcode auf die Album-ID zugreifen können.
Es ist nicht immer möglich, Elementen eindeutige IDs hinzuzufügen, wie z. B. Zeilen in einem Raster oder Elemente in einer Liste. In solchen Fällen können Sie CSS-Klassen und HTML-Datenattribute verwenden, um den Elementen nachverfolgbare Eigenschaften zur leichteren Auswahl hinzuzufügen. Wenn Sie z. B. zwei Listen von Alben auf Ihrer Seite hatten, eine als Ergebnis der Benutzersuche und eine andere für vorgeschlagene Alben, die auf den vorherigen Käufen des Benutzers basieren, können Sie diese anhand einer CSS-Klasse unterscheiden ul
Element, auch wenn diese Klasse nicht zum Stylen der Liste verwendet wird:
Wenn Sie keine unbenutzten CSS-Klassen verwenden möchten, können Sie stattdessen HTML-Datenattribute verwenden und die Listen folgendermaßen ändern:
und:
Einer der Hauptgründe, warum UI-Tests fehlschlagen, ist, dass ein Element oder Text auf der Seite nicht gefunden wird. Dies geschieht manchmal, weil Sie aufgrund von Navigationsfehlern oder Änderungen an den Seitennavigationen Ihrer Website oder aufgrund von Überprüfungsfehlern auf einer falschen Seite landen. Zu anderen Zeiten kann es an einer fehlenden Seite oder einem Serverfehler liegen.
Unabhängig davon, was den Fehler verursacht und ob Sie dies in Ihrem CI-Serverprotokoll oder in Ihrer Desktop-Testkonsole erhalten, a NoSuchElementException
(oder ähnliches) ist nicht sehr nützlich, um herauszufinden, was falsch gelaufen ist, oder? Wenn der Test fehlschlägt, besteht die einzige Möglichkeit, den Fehler zu beheben, darin, ihn erneut auszuführen und den Fehler zu überwachen. Es gibt einige Tricks, durch die Sie möglicherweise langsame UI-Tests zur Fehlerbehebung erneut ausführen müssen. Eine Lösung für dieses Problem besteht darin, einen Screenshot zu erstellen, wenn ein Test fehlschlägt, damit wir später darauf zurückgreifen können.
Es gibt eine Schnittstelle in Selenium ITakesScreenshot
:
////// Definiert die Schnittstelle, die zum Aufnehmen von Screenshots des Bildschirms verwendet wird. /// öffentliche Schnittstelle ITakesScreenshot ////// Bekommt ein /// ///Objekt, das das Bild der Seite auf dem Bildschirm darstellt. /// /// EIN Screenshot GetScreenshot ();Objekt, das das Bild enthält. ///
Diese Schnittstelle wird von Webtreiberklassen implementiert und kann folgendermaßen verwendet werden:
var screenshot = driver.GetScreenshot (); screenshot.SaveAsFile ("", ImageFormat.Png);
Wenn ein Test fehlschlägt, weil Sie sich auf einer falschen Seite befinden, können Sie dies anhand des aufgenommenen Screenshots schnell feststellen.
Auch das Aufnehmen von Screenshots reicht nicht immer aus. Sie können beispielsweise das erwartete Element auf der Seite sehen, der Test schlägt jedoch immer noch fehl, da er es nicht findet. Möglicherweise ist dies auf die falsche Auswahl zurückzuführen, die zu einer erfolglosen Elementsuche führt. Anstelle des Screenshots (oder als Ergänzung) können Sie die Seitenquelle auch als HTML erfassen. Da ist ein Seitenquelltext
Eigentum an IWebDriver
Schnittstelle (die von allen Web-Treibern implementiert wird):
////// Ruft die Quelle der zuletzt vom Browser geladenen Seite ab. /// ////// Wenn die Seite nach dem Laden geändert wurde (z. B. durch JavaScript) ///, kann nicht garantiert werden, dass der zurückgegebene Text der der geänderten Seite entspricht. /// Bitte konsultieren Sie die Dokumentation des jeweiligen Treibers, um herauszufinden, ob der zurückgegebene Text den aktuellen Status der Seite /// oder den zuletzt vom Webserver gesendeten Text widerspiegelt. Die zurückgegebene Seitenquelle ist eine ///-Darstellung des zugrunde liegenden DOM: Erwarten Sie nicht, dass es /// formatiert oder auf dieselbe Weise wie die vom Webserver gesendete Antwort maskiert wird. /// Zeichenfolge PageSource get;
So wie wir es gemacht haben ITakesScreenshot
Sie können eine Methode implementieren, die die Seitenquelle erfasst und in einer Datei für eine spätere Überprüfung speichert:
File.WriteAllText ("", driver.PageSource);
Sie möchten nicht wirklich Screenshots und Seitenquellen aller von Ihnen besuchten Seiten und für die bestandenen Tests erfassen. Andernfalls müssen Sie Tausende von ihnen durchgehen, wenn tatsächlich etwas schief geht. Stattdessen sollten Sie sie nur erfassen, wenn ein Test fehlschlägt, oder wenn Sie weitere Informationen zur Fehlerbehebung benötigen. Um zu vermeiden, dass der Code mit zu vielen try-catch-Blöcken verschmutzt wird, und um Code-Duplizierungen zu vermeiden, sollten Sie alle Element-Lookups und Assertions in eine Klasse einordnen und sie mit try-catch einfassen und den Screenshot und / oder die Seitenquelle im catch-Block erfassen . Hier ist ein bisschen Code, den Sie zum Ausführen von Aktionen für ein Element verwenden könnten:
public void Execute (By by, Action)action) try var element = WebDriver.FindElement (by); Aktion (Element); catch var capturer = neuer Capturer (WebDriver); capturer.CaptureScreenshot (); capturer.CapturePageSource (); werfen;
Das Capturer
Klasse kann implementiert werden als:
public class Capturer public static string OutputFolder = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "FailedTests"); private schreibgeschützt RemoteWebDriver _webDriver; public Capturer (RemoteWebDriver webDriver) _webDriver = webDriver; public void CaptureScreenshot (Zeichenfolge Dateiname = Null) var camera = (ITakesScreenshot) _webDriver; var screenshot = camera.GetScreenshot (); var screenShotPath = GetOutputFilePath (Dateiname, "png"); screenshot.SaveAsFile (screenShotPath, ImageFormat.Png); public void CapturePageSource (Zeichenfolge Dateiname = Null) var filePath = GetOutputFilePath (Dateiname, "html"); File.WriteAllText (filePath, _webDriver.PageSource); private Zeichenfolge GetOutputFilePath (Zeichenfolge Dateiname, Zeichenfolge Dateinamenerweiterung) if (! Directory.Exists (OutputFolder)) Directory.CreateDirectory (OutputFolder); var windowTitle = _webDriver.Title; Dateiname = Dateiname? string.Format ("0 1. 2", windowTitle, DateTime.Now.ToFileTime (), fileExtension) .Replace (':', '.'); var outputPath = Path.Combine (OutputFolder, Dateiname); var pathChars = Path.GetInvalidPathChars (); var stringBuilder = neuer StringBuilder (Ausgabepfad); foreach (var item in pathChars) stringBuilder.Replace (item, '.'); var screenShotPath = stringBuilder.ToString (); return screenShotPath;
Diese Implementierung behält den Screenshot und die HTML-Quelle in einem Ordner namens FailedTests neben den Tests bei. Sie können ihn jedoch ändern, wenn Sie ein anderes Verhalten wünschen.
Obwohl ich nur für Selenium spezifische Methoden gezeigt habe, sind ähnliche APIs in allen mir bekannten Automatisierungsframeworks vorhanden und können problemlos verwendet werden.
In diesem Artikel sprachen wir über ein paar Tipps und Tricks für UI-Tests. Wir haben diskutiert, wie Sie eine spröde und langsame UI-Testsuite vermeiden können, indem Sie festgelegte Verzögerungen in Ihren Tests vermeiden. Anschließend haben wir besprochen, wie Sie spröde Selektoren und Tests vermeiden können, indem Sie die Selektoren sorgfältig auswählen und wie Sie Ihre UI-Tests debuggen, wenn diese fehlschlagen.
Der in diesem Artikel gezeigte Code befindet sich größtenteils im MvcMusicStore-Beispiel-Repository, das wir im letzten Artikel gesehen haben. Es ist auch erwähnenswert, dass eine Menge Code im MvcMusicStore von der Seleno-Codebase entliehen wurde. Wenn Sie also viele coole Tricks sehen möchten, sollten Sie Seleno auschecken. Haftungsausschluss: Ich bin Mitbegründer der TestStack-Organisation und Mitwirkender bei Seleno.
Ich hoffe, das, was wir in diesem Artikel besprochen haben, hilft Ihnen bei Ihren UI-Tests.