Ranorex: Pixelfarbe ermitteln

Bei manchen Testfällen ist es notwendig die aktuelle Hintergrundfarbe eines Oberflächenelements zu ermitteln.
WinForms / VB6 / usw. Oberflächen stellen diesen Wert nicht als Eigenschaft bereit, aus diesem Grund muss dieser Wert über einen anderen Weg abgefragt werden.

Der einfachste Weg ist es, ein Screenshot des Elements zu erzeugen und diesen dann mit der GetPixel Methode abfragen.
Ranorex stellt dazu z.B. die Methode

Report.Screenshot(element);

bereit.
Bei dieser Methode wird allerdings das Bild lokal gespeichert, dieses Vorgehen ist etwas fehleranfällig und vor allem unnötig.
Nach einer längerer Suche, bin ich auf die Methode Imaging.CaptureCompressedImage() gestoßen, diese liefert ein Bitmap Objekt zur Laufzeit zurück, ohne dass Bilder lokal gespeichert werden müssen.
Als Parameter kann ein Element vom Typ Adapter oder Element übergeben werden.

Hier ist eine Beispiels-Methode, mit der vom übergebenen Control die Hintergrundfarben ermittelt werden können.
Natürlich können auch die Pixel verändert bzw. parametrisiert werden.

public static string Color(Adapter ui_control)
{
   Bitmap bmp = Imaging.CaptureCompressedImage(ui_control);
   Color cElementColor = bmp.GetPixel(2, 2);
   return cElementColor.Name;
}
Geschrieben in How To,Ranorex | Keine Kommentare

Ranorex: Problem beim dynamischen Zugriff auf eine Webtabelle

Bei der Automatisierung einer Web-Applikation mit Ranorex, bin ich vor kurzem auf folgendes Problem gestoßen:

Die Tabelle besteht aus ca 10 Zeilen und 2 Header Zeilen.
Um einen flexibelen Zugriff zu ermöglichen, setze ich mir den Ranorex Pfad (Ranorex XPath) selbst zusammen.
Der Zugriff sollte in diesem Fall über “Zeilen / Spalten – Nummer” aus Sicht der Tabellenebene stattfinden.
Das Element setzte sich so zusammen:

element = tablepath + "//tr[" + row + "]/td[" + column + "]";

Alles soweit in Ordnung. Variablen row = 1 und column = 3 gesetzt, Ranorex Pfad wird richtig gefüllt und die td Zelle lässt sich, mit dem generierten Pfad, durch Ranorex Spy finden.

Der Versuch dieses Element per Methode TryFindSingle() während der Testdurchführung zu finden, ist aber gescheitert.

Host.Local.TryFindSingle(element, TimeSpan.FromSeconds(time), out tdElement))

Nach einer kurzen Try/Fail-Phase, habe ich versucht die Zelle über den Ranorex Typ “WebElement” zu finden.
Dazu wird einfach das letzte Element (td) durch ein * ersetzt und mit TryFindSingle nach Typ “WebElement” gesucht.
Dadurch kann jedes Element identifiziert werden, das den Suchkriterien entspricht. Als Result kam Tag TH (Head Element) raus.
Also row = 3 (von der Anzahl höher als das letzte TH Element) gesetzt, schon hat der Zugriff über TryFindSingle() funktioniert.
Reicht als Lösung des Problems natürlich nicht aus, die ersten beiden Zeilen sollen schließlich auch angesprochen werden können. Da kommt das Element tbody ins Spiel.
Durch tbody kann hier sichergestellt werden, dass der Zugriff wirklich auf den “Content” der Tabelle stattfindet. Die Identifikation ist so eindeutig.
Also den Ranorex XPath Ausdruck angepasst, schon funktioniert die TryFindSingle() Suche fehlerfrei:

element = tablepath + "//tbody/tr[" + row + "]/td[" + column + "]";

Man könnte annehmen, dass //tr[1]/td[1] Kombination ausreichend wäre, dem war hier leider nicht so.
Warum dieser Pfad in Ranorex Spy richtig erkannt wird und per TryFindSingle() nicht, kann ich leider nicht sagen, aber durch diesen kleinen “Workaround” kann an dieser Stelle weitergearbeitet werden.

Im Ranorex Forum gibt es ein ähnliches Problem: Beitrag im Ranorex Forum
Die dort vorgeschlagenen Lösungen, haben bei diesem Problem aber keine Besserung gebracht.

Geschrieben in Ranorex,Webautomatisierung | Keine Kommentare

ClassCleanup() Verhalten

Um aus Microsoft Test Manager automatisierte Testfälle (Unit Tests, Coded UI Tests, Ranorex, Selenium usw.) ansprechen zu können, müssen diese in Testmethoden “verpackt” werden.
Wie bekannt sind diese Methoden in eine Struktur des UnitTest Frameworks von Microsoft Visual Studio eingepflegt, die auch Initialisierungs- und Abschluss-Methoden bietet:

  • Initialisierung: ClassInitialize(), TestInitialize()
  • Abschluss: TestCleanup(), ClassCleanup()

nehmen wir mal an, wir haben 2 Testklassen mit je 2 Testfällen:

Klasse1: TC1, TC2
Klasse2: TC3, TC4

Wenn wir alle Testfälle markieren und per “Run” ausführen, werden natürlich auch die einzelnen Initialize / Cleanup Methoden ausgeführt.

Wie ist die Aufrufreihenfolge der einzelnen Initialisierungs / Abschlussmethoden?

Eigentlich würde folgende Reihenfolge der Initialisierung / Abschlussmethoden “logisch” erscheinen:

  • ClassInitialize Klasse1
  • TestInitialize TC1 / TestCleanup TC1
  • TestInitialize TC2 / TestCleanup TC2
  • ClassCleanup Klasse1
  • ClassInitialize Klasse2
  • TestInitialize TC3 / TestCleanup TC3
  • TestInitialize TC4 / Testcleanup TC4
  • ClassCleanup Klasse2

Wenn die Testfälle gestartet werden, kommt aber folgende Ausgabe:

  • ClassInitialize Klasse 1
  • TestInitialize TC1 / TestCleanup TC1
  • TestInitialize TC2 / TestCleanup TC2
  • ClassInitialize Klasse 2
  • TestInitialize TC3 / TestCleanup TC3
  • TestInitialize TC4 / Testcleanup TC4
  • ClassCleanup Klasse 1
  • ClassCleanup Klasse 2

Die Klasse wird wie vermutet mit dem ersten Testfall einer Klasse initialisiert, aber erst aufgeräumt, nachdem alle Testfälle, aller Klassen, abgeschlossen sind.
Das liegt daran, dass bei der normalen Durchführung, eine Aufruf-Reihenfolge der einzelnen Testfälle nicht sichergestellt werden kann.

Muss vor dem Aufruf der zweiten Klasse sichergestellt sein, dass die erste Klasse abgeschlossen ist (z.B. Filezugriff), kann es entweder durch Ordered Tests oder durch Auslagerung der Initialisierung / Abschlusslogik  in die TestInitialize / Cleanup Methoden realisiert werden.

Geschrieben in Microsoft Test Manager,Ranorex,Selenium,Unit Tests,Visual Studio Testframework,VS UI Automatisierung | Keine Kommentare