Sebastian Basner / / 1 Entwicklung einer GUI Testsoftware für WPF Diplomkolloquium Sebastian Basner Matrikel-Nr.:
Sebastian Basner / / 2 Entwicklung einer GUI Testsoftware für WPF Aufgabenstellung Entwicklung einer GUI Testsoftware mit Record & Replay Funktionalität für WPF
Sebastian Basner / / 3 Entwicklung einer GUI Testsoftware für WPF Themen ● Überblick über UI Automation ● Implementierung ● Fazit und Ausblick
Sebastian Basner / / 4 Entwicklung einer GUI Testsoftware für WPF Überblick über UI Automation
Sebastian Basner / / 5 Entwicklung einer GUI Testsoftware für WPF UI Automation ● Nachfolgetechnologie von Microsoft Active Accessibility (MSAA) ● Teil der Windows Automation API ● Zielsetzungen: – Unterstützung von Behinderten – Automatisierung für UI Tests ● Cross Plattform „by design“
Sebastian Basner / / 6 Entwicklung einer GUI Testsoftware für WPF UI Automation ● Steuern von: – WPF – Forms – Win32 – GTK (als GTK# durch Novell implementiert)
Sebastian Basner / / 7 Entwicklung einer GUI Testsoftware für WPF UI Automation ● Elementidentifikation über: – Baumstruktur mit Desktop als root – Automation ID (Anwendung) – Control ID (Steuerelement) ● Zugriff über UI Automation Control Patterns
Sebastian Basner / / 8 Entwicklung einer GUI Testsoftware für WPF Implementierung ● Das GUI ● Festlegen der Testapplikation/Testelemente ● Skript Recording ● Testskript im Überblick ● Skript Replay
Sebastian Basner / / 9 Entwicklung einer GUI Testsoftware für WPF Das GUI
Sebastian Basner / / 10 Entwicklung einer GUI Testsoftware für WPF Das GUI ● WPF ● Panels und Grids ● Möglichst simpel für geringe Einstiegshürde ● Logfenster in der Mitte zur Kontrolle; kein editieren
Sebastian Basner / / 11 Entwicklung einer GUI Testsoftware für WPF Festlegen der Testapplikation ● Referenzierung der Testapplikation ● Aufbau eines Automation Baumes ● Wurzelelement ● Kindelemente ersten und zweiten Grades ● Datentyp AutomationElement
Sebastian Basner / / 12 Entwicklung einer GUI Testsoftware für WPF Festlegen der Testapplikation ● Anwendung muss vollständig gestartet sein ● Desktop ist Wurzelelement AutomationElement aeDesktop = AutomationElement.RootElement; ● Applikationen sind Kinder
Sebastian Basner / / 13 Entwicklung einer GUI Testsoftware für WPF Festlegen der Testapplikation ● Testapplikation finden über Prozessvariable p ● Alternativ über AutomationID ● Referenz auf Hauptfenster aeForm = AutomationElement.FromHandle(p.MainWindowHandle);
Sebastian Basner / / 14 Entwicklung einer GUI Testsoftware für WPF Festlegen der Testelemente ● Im Automation Baum Kindelemente der Applikationen ● Identifikation über Control ID ● Ablegen in AutomationElement AutomationElement ae = aeForm.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, ControlID)); ● Gefahr von manueller Doppelbenennung der Control ID
Sebastian Basner / / 15 Entwicklung einer GUI Testsoftware für WPF Skript Recording ● Kann bei manueller Erstellung übersprungen werden ● Testapplikation muss über GUI gestartet werden ● Eventbasiert
Sebastian Basner / / 16 Entwicklung einer GUI Testsoftware für WPF Skript Recording ● Registrieren eines neuen Eventhandlers AutomationEventHandler invokeHandler = new AutomationEventHandler(OnInvoke); ● Abonnieren des Events Automation.AddAutomationEventHandler(InvokePattern. InvokedEvent, aeForm, TreeScope.Descendants, invokeHandler);
Sebastian Basner / / 17 Entwicklung einer GUI Testsoftware für WPF Skript Recording private void OnInvoke(object source, AutomationEventArgs e) { AutomationElement ae = source as AutomationElement; events.Add("wrapper.Invoke(\"" + ae.Current.AutomationId + "\");"); string result = "Sie haben den Button " + ae.Current.AutomationId + " gedrückt"; GetRecordEventArgs es = new GetRecordEventArgs(result); onGetRecord(es); }
Sebastian Basner / / 18 Entwicklung einer GUI Testsoftware für WPF Testskript im Überblick ● C# statt eigene Skriptsprache ● Einfach änderbar ● Auf das Nötigste beschränkt ● Durch jede andere.NET Sprache ersetzbar
Sebastian Basner / / 19 Entwicklung einer GUI Testsoftware für WPF Testskript im Überblick wrapper.SetValue("textBox1", "1"); wrapper.SetValue("textBox1", "15"); wrapper.SetValue("textBox1", "1556"); wrapper.SetValue("textBox2", "1"); wrapper.SetValue("textBox2", "12"); wrapper.Invoke("button1"); wrapper.GetText("textBox3", "1568"); wrapper.Toggle("quadrierer"); wrapper.GetText("textBox3", " "); wrapper.errors(); Controller.CloseApp();
Sebastian Basner / / 20 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Kompilierung zur Laufzeit über CodeDOM ● Übergebene Assemblys, DLLs und Objektinstanzen werden hier definiert ● CompileUnit als oberstes Baumelement – CodeCompileUnit compU = new CodeCompileUnit(); ● Namespace Definition – CodeNamespace nameSpace = new CodeNamespace("UIASkript");
Sebastian Basner / / 21 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Skriptklasse: – Codetype erstellen – Zur Klasse machen CodeTypeDeclaration className = new CodeTypeDeclaration("Skript"); className.IsClass = true;
Sebastian Basner / / 22 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Skriptmethode: – Instanz vom Typ CodeMemberMethod – Attribute festlegen – Rückgabewert festlegen – Namen festlegen CodeMemberMethod methodName = new CodeMemberMethod(); methodName.Attributes = MemberAttributes.Public; methodName.ReturnType = new CodeTypeReference(typeof(void)); methodName.Name = "testSkript";
Sebastian Basner / / 23 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Benötigte DLLs in Namespace importieren nameSpace.Imports.Add(new CodeNamespaceImport("System")); ● Klasseninstanzen für Methode bereitstellen methodName.Parameters.Add(new CodeParameterDeclarationExpression(typeof(IAWrapper), "wrapper")); ● Skript auslesen methodName.Statements.Add(new CodeSnippetExpression(ReadFile(content)));
Sebastian Basner / / 24 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Baum zusammensetzen compU.Namespaces.Add(nameSpace); nameSpace.Types.Add(className); className.Members.Add(methodName); ● Compilerparameter übergeben CompilerParameters compilerParameters = new CompilerParameters((string[])assemblyNames.ToArray()); compilerParameters.GenerateInMemory = true; compilerParameters.CompilerOptions = "/target:library /optimize";
Sebastian Basner / / 25 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Kompilieren Microsoft.CSharp.CSharpCodeProvider csc = new Microsoft.CSharp.CSharpCodeProvider(); res = csc.CompileAssemblyFromDom(compilerParameters, compU); ● Skript ruft Automatisierungsmethoden im Wrapper auf ● Identifizieren des Elements über Control ID
Sebastian Basner / / 26 Entwicklung einer GUI Testsoftware für WPF Skript Replay ● Ausführen des Skriptbefehls über AutomationPatterns InvokePattern ip = (InvokePattern)ae.GetCurrentPattern(InvokePattern.Patter n); ip.Invoke(); ● Rückmeldungen ans GUI string result = "Es wurde der Button " + ae.Current.AutomationId + " gedrückt"; GetTextEventArgs e = new GetTextEventArgs(result); onGetText(e);
Sebastian Basner / / 27 Entwicklung einer GUI Testsoftware für WPF Fazit
Sebastian Basner / / 28 Entwicklung einer GUI Testsoftware für WPF Fazit ● WPF GUI Testtool erfolgreich erstellt ● Nicht „Feature Complete“ – Steuerbare Bedienelemente noch zu vervollständigen ● Stabil ● Diverse Erweiterungsszenarien denkbar – Weitere GUI Typen – Andere „Skriptsprachen“
Sebastian Basner / / 29 Entwicklung einer GUI Testsoftware für WPF Vielen Dank für Ihre Aufmerksamkeit!