Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 17 Min.

Oberfläche automatisieren

UI-Tests zu automatisieren ist eine heikle Sache. Die Bibliothek FlaUI nimmt den Schrecken.
© dotnetpro
Durch die Automatisierung von Benutzerschnittstellen können Entwicklungs- und Qualitätssicherungsteams ihre Testprozesse beschleunigen, die Testab­deckung erhöhen und die Zuverlässigkeit von Anwendungen verbessern. Während manuelle Tests zeitaufwendig und fehleranfällig sind, liefern automatisierte UI-Tests konsistente und wiederholbare Ergebnisse.Darüber hinaus ermöglicht die UI-Automatisierung eine kontinuierliche Integra­tion und Bereitstellung (CI/CD), indem sie sicherstellt, dass Änderungen am Code sofort getestet und validiert werden.Die Notwendigkeit von UI-Tests führte zu einer Vielzahl von Tools und Bibliotheken, die für die UI-Automatisierung zur Verfügung stehen. Zu den bekanntesten gehören Selenium, das vor allem für Webanwendungen verwendet wird, und TestStack.White, eine Bibliothek zur Automatisierung von Desktop-Anwendungen.FlaUI ist eine weitere wichtige Bibliothek, die speziell für .NET-Anwendungen entwickelt wurde und eine einfache und flexible Lösung für die Automatisierung von Benutzeroberflächen bietet.In dieser Episode der Frameworks-Kolumne liegt der Fokus auf der Bibliothek FlaUI zur UI-Automatisierung im Kontext von .NET und C#. Zudem stellt der Artikel andere Bi­bliotheken vor, um einen umfassenderen Gesamteindruck zu geben. FlaUI ist gut, aber nicht für alle Anwendungsfälle geeignet, sodass ein Blick über den Tellerrand wichtig ist.

Einführung in FlaUI

FlaUI steht für „Flexible Automation UI“ und ist entstanden, um Entwicklern und Testern eine einfache, aber leistungsfähige Möglichkeit zu bieten, Interaktionen mit Benutzeroberflächen zu automatisieren. Die Bibliothek basiert auf der UI Automation (UIA) [1] von Microsoft, einer Technologie, die es ermöglicht, Benutzeroberflächen zu analysieren und mit ihnen zu interagieren. FlaUI unterstützt verschiedene UI-Frameworks wie Windows Forms, Windows Presentation Foundation (WPF) und Anwendungen, die auf der Universal Windows Platform (UWP) basieren.Die Entwicklung von FlaUI begann als Reaktion auf die Limitierungen und Herausforderungen, die andere UI-Automatisierungstools mit sich brachten. Besonders im .NET-Ökosystem gab es Bedarf für eine flexible, robuste und gut do­kumentierte Automatisierungsbibliothek. Roman Baudis initiierte FlaUI und entwickelte die Bibliothek vollständig in C#, was eine nahtlose Integration in .NET-Projekte ermöglicht. FlaUI ist Open Source, steht unter der MIT-Lizenz und der Quelltext ist über GitHub verfügbar [2].Ursprünglich war FlaUI als eine Alternative zu TestStack.White und ähnlichen Tools angedacht. FlaUI lässt sich in einer Vielzahl von Szenarien zur UI-Automatisierung einsetzen. Einer der Hauptanwendungsbereiche von FlaUI ist die Erstellung automatisierter UI-Tests. Diese Tests können sicherstellen, dass Benutzerinteraktionen wie Klicks, Texteingaben und Navigation korrekt funktionieren, was Regressionen verhindert. Darüber hinaus lässt sich FlaUI gut in CI/CD-Pipelines integrieren. Dadurch ist es möglich, automatisierte UI-Tests nach jeder Codeänderung automatisch auszuführen, um sicherzustellen, dass die Anwendung weiterhin korrekt funktioniert.Eine weitere Testart sind Tests zur Sicherstellung der Barrierefreiheit. Hierbei lässt sich automatisiert feststellen, ob UI-Elemente für Benutzer mit Einschränkungen zugänglich sind. Gänzlich andere Anwendungsfälle sind die Datenextraktion und Dateneingabe. Durch die Möglichkeit der UI-Steuerung lassen sich Daten aus Benutzeroberfläche auslesen beziehungsweise dort eingeben, was in Automatisierungslösungen wichtig ist.

Technische Grundlagen

Die Architektur von FlaUI ist darauf ausgelegt, eine flexible und erweiterbare Lösung für die UI-Automatisierung zu bieten, die verschiedene UI-Frameworks wie WinForms, WPF und UWP unterstützt. Das Projekt nutzt einige technische Implementierungen, um seine Funktionalitäten anbieten zu können.Zunächst ist da die Abstraktionsschicht, um die Unterschiede zwischen den verschiedenen UI-Technologien zu verbergen. Dies bedeutet, dass die gleichen Automatisierungsskripte auf unterschiedlichen UI-Technologien funktionieren können, ohne dass Anpassungen erforderlich sind. Die Kernkomponente von FlaUI ist ein Wrapper um das UI Automation API von Microsoft, das Interaktionen mit Benutzeroberflächen ermöglicht. FlaUI bietet eine objektorientierte und stark typisierte Schnittstelle zu diesem API, was die Entwicklung von Automatisierungsskripten vereinfacht.Darüber hinaus nutzt FlaUI sogenannte Pattern- und Property-Module, um die Funktionalität der UI-Elemente zu beschreiben. Patterns definieren, welche Aktionen auf einem UI-Element durchgeführt werden können. Beispielsweise das InvokePattern für Buttons, das ValuePattern für Textboxen und dergleichen. Properties liefern dagegen Informationen über die Eigenschaften eines UI-Elements. Solche Informationen sind zum Beispiel der Name oder der Zustand eines Elements.Zusätzlich bietet FlaUI eine Vielzahl von Helper-Methoden, die häufig auftretende Automatisierungsaufgaben vereinfachen. Beispiele dafür sind das Finden von UI-Elementen, das Senden von Tastatureingaben und das Klicken auf Buttons. Diese Methoden abstrahieren die Komplexität der direkten UIA-Interaktionen und machen den Code besser lesbar und wartbar.

UI Automation von Microsoft (UIA)

UI Automation (UIA) von Microsoft ist ein Framework zur Automatisierung von Benutzeroberflächen (UI). Es ermöglicht, auf UI-Elemente in Anwendungen zuzugreifen und diese zu steuern, was sowohl für Testautomatisierung als auch für Barrierefreiheit entscheidend ist. UIA bietet eine standardisierte Möglichkeit, mit verschiedenen UI-Komponenten zu interagieren, unabhängig von der zugrunde liegenden Technologie oder Plattform.Ein zentraler Bestandteil von UIA ist der UI Automation Tree, eine hierarchische Struktur, die alle UI-Elemente einer Anwendung darstellt. Dieser Baum besteht aus drei Haupttypen von Knoten: Raw View, Control View und Content View. Jeder Knoten bietet unterschiedliche Ebenen von Detailgenauigkeit und Filterung, je nach den Anforderungen der Automatisierung.UIA-Clients, wie Testautomatisierungstools oder assistive Technologien, nutzen UIA-Provider, die von den Anwendungen implementiert werden, um Informationen über ihre UI-Elemente bereitzustellen. Dies ermöglicht es den Clients, ­Aktionen durchzuführen wie etwa Klicken, Eingaben tätigen oder Statusinforma­tionen abrufen. Ein weiteres wichtiges Merkmal von UIA ist die Unterstützung von Ereignissen. UIA kann auf verschiedene Ereignisse innerhalb des UI reagieren, wie zum Beispiel Änderungen des Fokus, Elementänderungen oder Eigenschaftsänderungen. Dies ermöglicht eine dynamische und reaktionsfähige Automatisierung.

Accessibility Insights for Windows

Der Zugriff auf UI-Elemente kann recht umständlich sein, da nicht immer eindeutig zu erkennen ist, welche Typen von Elementen zum Einsatz kommen oder über welchen UI-Pfad diese erreichbar sind. Hier helfen Tools weiter, mit denen sich der Aufbau einer Oberfläche näher betrachten lässt.Accessibility Insights for Windows [3] ist ein solches leistungsstarkes Open-Source-Tool, das von Microsoft entwickelt wurde, um dabei zu helfen, die Barrierefreiheit ihrer Windows-Anwendungen zu verbessern. Ziel ist es, sicherzustellen, dass Anwendungen für alle Benutzer zugänglich sind, einschließlich Menschen mit Behinderungen. Dies ist nicht nur eine ethische Verpflichtung, sondern auch eine gesetzliche Anforderung in vielen Ländern.Accessibility Insights hilft dabei, die Einhaltung von Barrierefreiheitsstandards wie den Web Content Accessibility Guidelines (WCAG) und der Anforderungen des Americans with Disabilities Act (ADA) zu gewährleisten.Mit der Live-Inspect-Funktion können Benutzer in Echtzeit durch die UI-Elemente einer Anwendung navigieren und deren Barrierefreiheitsinformationen anzeigen. Dies umfasst Eigenschaften wie Name, Rolle, Zustand und die unterstützten Barrierefreiheits-APIs (siehe Bild 1).
Screenshot des Accessibility Tools für Windows am Beispiel von Word (Bild 1) © Autor

Installation und die ersten Automatisierungen

Um FlaUI in einem .NET/C#-Projekt zu verwenden, sind einige einfache Schritte notwendig. Zunächst ist die Entscheidung zu treffen, ob UIA 2 oder UIA 3 zum Einsatz kommen soll, siehe dazu den Kasten UIA2 versus UIA3 mit dem Vergleich. Da es für beide unterschiedliche Assemblies gibt, sind die korrekten in einem Projekt zu referenzieren. Unter der Annahme, dass Version 3 passt, braucht das Projekt die folgenden beiden grundlegenden Pakete:

UIA2 versus UIA3

UIA2 (UI Automation 2) bezieht sich auf die ältere Version des UI-Automation-Frameworks, das in Windows 7 und früheren Versionen eingeführt wurde. UIA2 bietet grundlegende Automatisierungsfunktionen und wird von FlaUI verwendet, um mit älteren Anwendungen und Systemen zu interagieren. Es ist besonders nützlich für die Automatisierung von Anwendungen, die auf älteren Windows-Plattformen laufen, da es auf dieser etablierten Technologie basiert.

Install-<span class="hljs-keyword">Package</span> <span class="hljs-title">FlaUI.Core</span>
<span class="hljs-title">Install-<span class="hljs-keyword">Package</span> FlaUI.UIA3</span> 
Sind die Pakete im Projekt verfügbar, lässt sich die erste Automatisierung einfügen. Das Beispielprojekt nutzt dazu ein Windows-Forms-Projekt auf Basis von .NET 8 und C# 12. Der folgende Code ist die erste Automatisierung der Anwendung Notepad unter Windows 10.

<span class="hljs-keyword">var</span> <span class="hljs-keyword">app</span> = FlaUI.Core.Application.Launch(<span class="hljs-string">"notepad.exe"</span>);
using <span class="hljs-keyword">var</span> automation = new UIA3Automation();
<span class="hljs-keyword">var</span> <span class="hljs-keyword">window</span> = <span class="hljs-keyword">app</span>.GetMainWindow(automation);
Console.WriteLine(<span class="hljs-keyword">window</span>.Title); 
Als Resultat öffnet sich Notepad und erhält den Fokus. Nach dem Einrichten der Projektstruktur und dem ersten Beispiel können wir das erste richtige Automatisierungsskript beginnen. Listing 1 zeigt dazu ein minimales Beispiel, das auf dem vorherigen Code basiert, um Notepad unter Windows zu starten. Ist die Anwendung gestartet und besteht Zugriff auf das Hauptfenster im Code, sucht die nächste Zeile nach dem ersten Kind-Element des Typs Document. Damit ist die Eingabe gemeint, um Text einzufügen. Anschließend lässt sich dort programmatisch Text eingeben.
Listing 1: Die erste Automatisierung für Notepad
// Text &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; Notepad eingeben.&lt;br/&gt;var &lt;span class="hljs-attr"&gt;textBox&lt;/span&gt; = window.FindFirstChild(&lt;br/&gt;  &lt;span class="hljs-attr"&gt;cf&lt;/span&gt; =&amp;gt; cf.ByControlType(ControlType.Document))&lt;br/&gt;    .AsTextBox();&lt;br/&gt;textBox.Enter(&lt;span class="hljs-string"&gt;"Hallo von FlaUI!"&lt;/span&gt;);&lt;br/&gt;// Datei speichern.&lt;br/&gt;Keyboard.Pressing(VirtualKeyShort.CONTROL, &lt;br/&gt;  VirtualKeyShort.KEY_S);&lt;br/&gt;// Warten, bis das modale Fenster verfügbar ist.&lt;br/&gt;var &lt;span class="hljs-attr"&gt;result&lt;/span&gt; = Retry.WhileEmpty(&lt;br/&gt;  () =&amp;gt; window.ModalWindows).Result;&lt;br/&gt;// Dateiname eingeben und speichern&lt;br/&gt;var &lt;span class="hljs-attr"&gt;saveWindow&lt;/span&gt; = window.ModalWindows[&lt;span class="hljs-number"&gt;0&lt;/span&gt;];&lt;br/&gt;var &lt;span class="hljs-attr"&gt;fileNameBox&lt;/span&gt; = saveWindow.FindFirstDescendant(&lt;br/&gt;  &lt;span class="hljs-attr"&gt;cf&lt;/span&gt; =&amp;gt; cf.ByControlType(ControlType.ComboBox))&lt;br/&gt;    .AsComboBox();&lt;br/&gt;fileNameBox.&lt;span class="hljs-attr"&gt;Value&lt;/span&gt; = &lt;br/&gt;  @&lt;span class="hljs-string"&gt;"C:\Users\Fabia\Desktop\FlaUITest.txt"&lt;/span&gt;;&lt;br/&gt;saveWindow.Focus();&lt;br/&gt;Keyboard.Press(VirtualKeyShort.ENTER); 
Danach kann der Code die Tastenkombination [Strg] + [S] ausführen, um das gerade veränderte Dokument zu speichern. Der nachfolgende Code wartet, bis der modale Dialog verfügbar ist, und sucht dort dann die Eingabe für den Dateinamen, um das Speichern mit der Eingabetaste zu bestätigen.Dieses einfache Skript zeigt die grundlegenden Schritte zur Automatisierung einer Anwendung mit FlaUI. Es demons­triert, wie Anwendungen gestartet, UI-Elemente gefunden und Interaktionen wie Texteingabe und Tastaturbefehle durchgeführt werden können. Was das Skript nicht direkt deutlich macht, ist, wie viel dabei schieflaufen kann und wie wenig intuitiv die Automatisierung der Fenster und Elemente darin sein kann.Beispielsweise ist der modale Dialog zum Speichern der neuen Datei nicht sofort in der Collection der modalen Fenster verfügbar. Das dauert eine Weile, und so wartet die Anweisung mit Retry.WhileEmpty() darauf, dass die Auflistung mit den modalen Fenstern nicht mehr leer ist. Erst dann kann der Code fortfahren.Eine Alternative dazu ist ein Aufruf von Thread.Sleep(). Das ist unschöner, da die Wartezeit variieren kann, was die Retry-Klassen zu umgehen versteht.Darüber hinaus ist es nicht immer einfach, die richtigen Elemente zu finden. Beispielsweise beim Zugriff auf das Editor-Element, um dort Text einzufügen. Eine Möglichkeit wäre, über den Typ des Elements zu suchen und anzunehmen, dass es sich dabei um ein Edit-Element handelt. Wir müssen aber, wie im Code zu sehen, ControlType.Document nutzen, um das Element finden und ansteuern zu können – ebenso wie bei dem Element für den Dateinamen, um den Text zu speichern. Das ist ebenfalls kein Edit-Element, sondern eine ComboBox.Warum diese Art Steuerelement? Das Auswahlfeld mit dem Pfeil, um die vorherigen Dateinamen anzuzeigen, macht das ganze Element zu einem Auswahlfeld. Das sind typische Szenarien, die beim Ansteuern von Anwendungen auftreten können. Insbesondere gilt das für die Automatisierung von Legacy-Anwendungen, die nicht mit .NET entstanden sind.

Abstraktion von UI-Frameworks

FlaUI unterstützt eine große Anzahl von UI-Frameworks, was es zu einem vielseitigen Werkzeug für die Automatisierung von Benutzeroberflächen macht. Diese Unterstützung ermöglicht es, Automatisierungsskripte zu erstellen, die auf unterschiedlichen UI-Technologien laufen, ohne signifikante Änderungen am Code vornehmen zu müssen.Listing 2 zeigt dazu ein Beispiel. Der Code startet eine fiktive Anwendung, die mit Windows Forms oder Windows Presenta­tion Foundation implementiert sein kann. Die beiden Beispiele zum Auffinden und Ausführen eines Buttons unterscheiden sich lediglich durch die Variablennamen. Der Code ist identisch, da FlaUI sich nach außen hin nicht um die Unterschiede kümmert – sie werden durch das API abstrahiert.
Listing 2: Gleiche Ansteuerung für Windows Forms und WPF
// WinForms- oder WPF-Anwendung starten&lt;br/&gt;var &lt;span class="hljs-attr"&gt;process&lt;/span&gt; = Process.Start(&lt;span class="hljs-string"&gt;"path-to-app.exe"&lt;/span&gt;);&lt;br/&gt;var &lt;span class="hljs-attr"&gt;app&lt;/span&gt; = FlaUI.Core.Application.Attach(process);&lt;br/&gt;var &lt;span class="hljs-attr"&gt;window&lt;/span&gt; = app.GetMainWindow(automation);&lt;br/&gt;// Interaktion mit WinForms-Anwendung&lt;br/&gt;var &lt;span class="hljs-attr"&gt;winFormsButton&lt;/span&gt; = winFormsWindow.FindFirstDescendant(&lt;span class="hljs-attr"&gt;cf&lt;/span&gt; =&amp;gt; &lt;br/&gt;  cf.ByAutomationId(&lt;span class="hljs-string"&gt;"winFormsButton"&lt;/span&gt;)).AsButton();&lt;br/&gt;winFormsButton.Invoke();&lt;br/&gt;// Interaktion mit WPF-Anwendung&lt;br/&gt;var &lt;span class="hljs-attr"&gt;wpfButton&lt;/span&gt; = wpfWindow.FindFirstDescendant(&lt;br/&gt;  &lt;span class="hljs-attr"&gt;cf&lt;/span&gt; =&amp;gt; cf.ByAutomationId(&lt;span class="hljs-string"&gt;"wpfButton"&lt;/span&gt;)).AsButton();&lt;br/&gt;wpfButton.Invoke(); 

Elementerkennung und -interaktion

Ein zentraler Bestandteil der UI-Automatisierung ist die Fähigkeit, UI-Elemente zu erkennen und mit ihnen zu interagieren. FlaUI bietet robuste Mechanismen zur Identifizierung und Interaktion mit UI-Elementen basierend auf verschiedenen Eigenschaften wie AutomationId, Name, ControlType und mehr.Die Elementerkennung per ControlType haben die vorherigen Beispiele bereits vielfach gezeigt. Wenn die Automa­tionId bekannt ist, lässt sich darüber ebenfalls sehr einfach ein Steuerelement finden, wie die nachfolgenden beiden Zeilen zeigen:

<span class="hljs-attribute">var textBox</span> = mainWindow.FindFirstDescendant(
  cf =&gt; cf.ByAutomationId(<span class="hljs-string">"textBoxId"</span>)).AsTextBox();
<span class="hljs-attribute">v</span><span class="hljs-attribute">a</span><span class="hljs-attribute">r</span> <span class="hljs-attribute">b</span><span class="hljs-attribute">u</span><span class="hljs-attribute">t</span><span class="hljs-attribute">t</span><span class="hljs-attribute">o</span><span class="hljs-attribute">n</span> = mainWindow.FindFirstDescendant(
  cf =&gt; cf.ByAutomationId(<span class="hljs-string">"buttonId"</span>)).AsButton(); 
FlaUI bietet dazu viele verschiedene Möglichkeiten an. Wichtig ist, welche Methoden zum Einsatz kommen, um ein Element zu finden. Dabei dreht sich vieles um die Find-Methoden. Einige davon zeigt das Bild 2. Beispielsweise bietet FlaUI die Option, einen direkten Nachfolger, ein Kind-Element, das erste Element aufgrund einer Bedingung oder alle verschachtelten Elemente zu finden.
Zahlreiche Beispiele für die Find-Methode (Bild 2) © Autor
Die Elementhierarchie spielt dabei eine zentrale Rolle, da die Find-Methoden diese durchlaufen. Sucht man nach ­einem Kind-Element, nutzt aber nicht diese Kinder als Suchbereich, wird der Code kein Element finden können. Das Gleiche gilt bei einem falschen Typ, nach dem gesucht wird.

Maus- und Tastatursteuerung sowie Screenshots

FlaUI ermöglicht die Steuerung von Maus und Tastatur, um Benutzerinteraktionen zu simulieren. Dies umfasst das Klicken, Bewegen und Drücken von Maustasten sowie das Senden von Tastatureingaben. Diese Funktionen sind besonders nützlich für Szenarien, in denen direkte UI-Element-Interaktionen nicht ausreichen oder nicht möglich sind. Der folgende Code zeigt dazu ein minimales Beispiel.

<span class="hljs-keyword">var</span> button = <span class="hljs-built_in">window</span>.FindFirstDescendant(
  <span class="hljs-function"><span class="hljs-params">cf</span> =&gt;</span> cf.ByAutomationId(<span class="hljs-string">"buttonId"</span>)).AsButton();
<span class="hljs-keyword">var</span> buttonPoint = 
  button.Properties.ClickablePoint.ValueOrDefault;
Mouse.MoveTo(buttonPoint);
Mouse.Click(MouseButton.Right); 
Er sucht nach einem Button über die AutomationId, speichert dann den klickbaren Punkt in einer Variablen, um diesen dazu zu nutzen, den Klick der rechten Maustaste zu simulieren.Damit lassen sich zahlreiche Szenarien simulieren, insbesondere in komplexeren Anwendungen, die zum Beispiel die Maus für die Steuerung nutzen, wie Simulationen oder Zeichenprogramme.FlaUI bietet darüber hinaus die Möglichkeit, Screenshots von UI-Elementen oder ganzen Fenstern zu erstellen. Diese Funktion ist nützlich für die Dokumentation von Tests oder zur Fehleranalyse, da sie visuelle Beweise für den Zustand der Anwendung zu einem bestimmten Zeitpunkt liefert.Nicht immer liefern Fehlermeldungen oder Testprotokolle aussagekräftige Ergebnisse. In manchen Szenarien bedarf es eines pixelgenauen Vergleichs von Resultaten. Hier können Screenshots helfen.Der folgende Code zeigt zwei Beispiele, um einmal einen Screenshot des gesamten Fensters und einmal einen von einem bestimmten Element zu erstellen.

// Screenshot des Fensters.
var screenshot = window.Capture();
screenshot.Save(
  @"C:<span class="hljs-symbol">\U</span>sers<span class="hljs-symbol">\F</span>abia<span class="hljs-symbol">\D</span>esktop<span class="hljs-symbol">\m</span>ainWindowScreenshot.png");
// Screenshot eines bestimmten UI-Elements
var buttonScreenshot = fileNameBox.Capture();
buttonScreenshot.Save(
  @"C:<span class="hljs-symbol">\U</span>sers<span class="hljs-symbol">\F</span>abia<span class="hljs-symbol">\D</span>esktop<span class="hljs-symbol">\b</span>uttonScreenshot.png"); 
Bild 3 zeigt den Screenshot des gesamten Fensters und Bild 4 den des Steuerelements. Das Beispiel hat den Screenshot von der ComboBox erstellt, die den Dateinamen zum Speichern aufnimmt.
Screenshot der gesamten Anwendung (Bild 3) © Autor
Screenshot eines einzelnen UI-Elements (Bild 4) © Autor

Dynamische Elemente und verschachtelte Strukturen

Die Automatisierung komplexer Anwendungen erfordert eine subtilere Herangehensweise, um die unterschiedlichen UI-Komponenten und ihre Interaktionen effizient zu handhaben. FlaUI bietet hier die nötigen Tools und Techniken, um auch komplexe Szenarien zu meistern. Zwei häufige Herausforderungen sind dynamische UI-Elemente und verschachtelte UI-Strukturen.Viele moderne Anwendungen nutzen dynamische UI-Elemente, deren Eigenschaften sich zur Laufzeit ändern. FlaUI ermöglicht das dynamische Auffinden und Interagieren mit solchen Elementen durch flexible Abfragefunktionen.Komplexe Anwendungen haben zudem oft tief verschachtelte UI-Strukturen. FlaUI kann in diesen Strukturen durch seine Fähigkeit zur rekursiven Suche nach UI-Elementen effektiv navigieren. Dazu sind die vielen verschiedenen Find-Methoden nützlich, die bereits weiter oben im Text vorgestellt wurden.Listing 3 zeigt einen Ausschnitt aus einem Automatisierungsskript, um auf ein Menü zuzugreifen. Menüs sind sehr häufig dynamisch, da sich die Menü-Elemente je nach Kontext anpassen. Beispielsweise kann es je nach erlaubter Aktion aktivierte oder deaktivierte Elemente geben, oder Elemente sind im Menü gar nicht vorhanden, wenn diese nicht erlaubt sind.
Listing 3: Die Interaktion mit einem komplexeren UI-Element (Menü)
// Beispiel: Interaktion mit einem &lt;br/&gt;// komplexen UI-Element&lt;br/&gt;var menu = mainWindow.FindFirstDescendant(&lt;span class="hljs-built_in"&gt;cf&lt;/span&gt; =&amp;gt; &lt;br/&gt;  &lt;span class="hljs-built_in"&gt;cf&lt;/span&gt;.ByControlType(FlaUI.Core.Definitions.ControlType&lt;br/&gt;    .Menu)).AsMenu();&lt;br/&gt;&lt;span class="hljs-built_in"&gt;var&lt;/span&gt; fileMenuItem = menu.Items[&lt;span class="hljs-string"&gt;"File"&lt;/span&gt;];&lt;br/&gt;fileMenuItem.Click();&lt;br/&gt;&lt;span class="hljs-built_in"&gt;var&lt;/span&gt; openMenuItem = fileMenuItem.SubItems[&lt;span class="hljs-string"&gt;"Open"&lt;/span&gt;];&lt;br/&gt;openMenuItem.Click(); 

Testdurchführung

Die Verwaltung und Durchführung von Testfällen ist ein wesentlicher Bestandteil der Qualitätssicherung in der Software­entwicklung. FlaUI lässt sich in bestehende Testfall-Verwaltungs-Tools integrieren, um die Automatisierung von Tests zu erleichtern. Dabei ist eine strukturierte Organisation der Testfälle entscheidend, um sicherzustellen, dass alle wichtigen Szenarien abgedeckt sind. Zudem ist es essenziell, die Test­fälle modular und wiederverwendbar aufzubauen, um Wartungsaufwand zu minimieren – gerade beim Einsatz von UI-Tests, denn viele Teile ähneln sich, gerade beim Testaufbau.Listing 4 zeigt eine einfache Testfallstruktur mit FlaUI und NUnit. Organisatorische Tätigkeiten wie die Instanzierung der UI-Automatisierung und das Starten der Anwendung unter Test werden in den Setup-Methoden erledigt.
Listing 4: Ein Testcase mit FlaUI und NUnit
&lt;span class="hljs-keyword"&gt;namespace&lt;/span&gt; &lt;span class="hljs-title"&gt;FlaUITestCases&lt;/span&gt;&lt;br/&gt;{&lt;br/&gt;  [TestFixture]&lt;br/&gt;  &lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title"&gt;ApplicationTests&lt;/span&gt;&lt;br/&gt;  {&lt;br/&gt;    &lt;span class="hljs-keyword"&gt;private&lt;/span&gt; Application app;&lt;br/&gt;    &lt;span class="hljs-keyword"&gt;private&lt;/span&gt; UIA3Automation automation;&lt;br/&gt;    [SetUp]&lt;br/&gt;    &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;SetUp&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;    &lt;/span&gt;{&lt;br/&gt;      automation = &lt;span class="hljs-keyword"&gt;new&lt;/span&gt; UIA3Automation();&lt;br/&gt;      app = FlaUI.Core.Application.Launch(&lt;br/&gt;        &lt;span class="hljs-string"&gt;"path_to_app.exe"&lt;/span&gt;);&lt;br/&gt;    }&lt;br/&gt;    [TearDown]&lt;br/&gt;    &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;TearDown&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;    &lt;/span&gt;{&lt;br/&gt;      app.Close();&lt;br/&gt;      automation.Dispose();&lt;br/&gt;    }&lt;br/&gt;    [Test]&lt;br/&gt;    &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;TestLogin&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;    &lt;/span&gt;{&lt;br/&gt;      &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; mainWindow = app.GetMainWindow(automation);&lt;br/&gt;      &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; usernameBox = mainWindow&lt;br/&gt;        .FindFirstDescendant(cf =&amp;gt; &lt;br/&gt;          cf.ByAutomationId(&lt;span class="hljs-string"&gt;"username"&lt;/span&gt;)).AsTextBox();&lt;br/&gt;      &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; passwordBox = mainWindow&lt;br/&gt;        .FindFirstDescendant(cf =&amp;gt; &lt;br/&gt;          cf.ByAutomationId(&lt;span class="hljs-string"&gt;"password"&lt;/span&gt;)).AsTextBox();&lt;br/&gt;      &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; loginButton = mainWindow&lt;br/&gt;        .FindFirstDescendant(cf =&amp;gt; &lt;br/&gt;          cf.ByAutomationId(&lt;span class="hljs-string"&gt;"login"&lt;/span&gt;)).AsButton();&lt;br/&gt;      usernameBox.Enter(&lt;span class="hljs-string"&gt;"testuser"&lt;/span&gt;);&lt;br/&gt;      passwordBox.Enter(&lt;span class="hljs-string"&gt;"password"&lt;/span&gt;);&lt;br/&gt;      loginButton.Invoke();&lt;br/&gt;      &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; welcomeLabel = mainWindow&lt;br/&gt;        .FindFirstDescendant(cf =&amp;gt; &lt;br/&gt;          cf.ByAutomationId(&lt;span class="hljs-string"&gt;"welcome"&lt;/span&gt;)).AsLabel();&lt;br/&gt;      Assert.AreEqual(&lt;span class="hljs-string"&gt;"Welcome, testuser!"&lt;/span&gt;, &lt;br/&gt;        welcomeLabel.Text);&lt;br/&gt;    }&lt;br/&gt;  }&lt;br/&gt;} 
Dadurch können sich die Testmethoden auf die konkreten Testfälle fokussieren. Diese Art der Integration ist mit zahlreichen Testframeworks möglich, beispielsweise auch mit xUnit. Und in Kombination mit einer Stopwatch lassen sich rudimentäre Performance- und Lasttests von UI-Anwendungen durchführen, denn die Stopwatch kann messen, wie lange es dauert, bis UI-Operationen durchgeführt sind.

Wiederverwendbare Komponenten und Module

Wiederverwendbare Komponenten und Module tragen zur Reduzierung von Code-Duplikation und zur Verbesserung der Wartbarkeit bei. Diese Komponenten sollten gut definiert und klar voneinander getrennt sein. Da es sich um die UI-Automatisierung handelt, kann das Page Object Pattern hilfreich sein, das ansonsten beim Testen von Websites angewandt wird.Listing 5 zeigt dazu ein Beispiel, bei dem eine fiktive Login-Page in einer Klasse abstrahiert wird. Die jeweiligen UI-Elemente sind über FlaUI adressiert. Diese Klasse lässt sich nun an verschiedenen Stellen im Automatisierungs-Prozess nutzen, ebenso wie in Tests.
Listing 5: Beispiel für ein Page Object
&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;class&lt;/span&gt; &lt;span class="hljs-title"&gt;LoginPage&lt;/span&gt;&lt;br/&gt;{&lt;br/&gt;  &lt;span class="hljs-keyword"&gt;private&lt;/span&gt; &lt;span class="hljs-keyword"&gt;readonly&lt;/span&gt; AutomationElement _parent;&lt;br/&gt;  &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-title"&gt;LoginPage&lt;/span&gt;(&lt;span class="hljs-params"&gt;AutomationElement parent&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;  &lt;/span&gt;{&lt;br/&gt;    _parent = parent;&lt;br/&gt;  }&lt;br/&gt;  &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;EnterUsername&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;span class="hljs-keyword"&gt;string&lt;/span&gt; username&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;  &lt;/span&gt;{&lt;br/&gt;    &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; usernameBox = &lt;br/&gt;      _parent.FindFirstDescendant(cf =&amp;gt; &lt;br/&gt;        cf.ByAutomationId(&lt;span class="hljs-string"&gt;"usernameId"&lt;/span&gt;)).AsTextBox();&lt;br/&gt;      usernameBox.Enter(username);&lt;br/&gt;  }&lt;br/&gt;  &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;EnterPassword&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;span class="hljs-keyword"&gt;string&lt;/span&gt; password&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;  &lt;/span&gt;{&lt;br/&gt;    &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; passwordBox = _parent.FindFirstDescendant(&lt;br/&gt;      cf =&amp;gt; cf.ByAutomationId(&lt;span class="hljs-string"&gt;"passwordId"&lt;/span&gt;))&lt;br/&gt;        .AsTextBox();&lt;br/&gt;      passwordBox.Enter(password);&lt;br/&gt;  }&lt;br/&gt;  &lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;public&lt;/span&gt; &lt;span class="hljs-keyword"&gt;void&lt;/span&gt; &lt;span class="hljs-title"&gt;ClickLogin&lt;/span&gt;(&lt;span class="hljs-params"&gt;&lt;/span&gt;)&lt;/span&gt;&lt;br/&gt;&lt;span class="hljs-function"&gt;  &lt;/span&gt;{&lt;br/&gt;    &lt;span class="hljs-keyword"&gt;var&lt;/span&gt; loginButton = _parent.FindFirstDescendant(&lt;br/&gt;      cf =&amp;gt; cf.ByAutomationId(&lt;span class="hljs-string"&gt;"loginButtonId"&lt;/span&gt;))&lt;br/&gt;        .AsButton();&lt;br/&gt;      loginButton.Invoke();&lt;br/&gt;  }&lt;br/&gt;} 

FlaUI versus White

White, oder TechStack.White [4], ist eine ältere UI-Automatisierungsbibliothek, die ebenfalls auf dem UIA-API von Microsoft basiert. Sie ist entstanden, um Desktop-Anwendungen zu automatisieren, und unterstützt hauptsächlich WinForms und WPF. White bietet ein einfaches API zur Interak­tion mit UI-Elementen und zur Durchführung von Automatisierungstests. Allerdings hat White im Lauf der Zeit weniger Aktualisierungen und Verbesserungen erfahren, was zu Einschränkungen bei der Unterstützung neuerer Technologien und UI-Frameworks geführt hat. Die Architektur von White ist weniger modular und weniger flexibel im Vergleich zu FlaUI, was die Anpassung an spezifische Anforderungen erschweren kann.White hat eine kleinere und weniger aktive Community im Vergleich zu FlaUI. Da White älter ist und weniger regelmäßig aktualisiert wird, hat die Entwicklerunterstützung im Lauf der Zeit abgenommen. Die Dokumentation von White ist weniger umfangreich und nicht immer auf dem neuesten Stand, was es für neu hinzukommende Benutzern schwieriger machen kann, sich in die Bibliothek einzuarbeiten. Trotz dieser Herausforderungen gibt es immer noch einige Entwickler, die White nutzen und unterstützen, insbesondere in bestehenden Projekten, die eine Migration zu neueren Bibliotheken wie FlaUI vermeiden wollen.Die Bibliothek White bietet ähnliche Grundfunktionen wie FlaUI einschließlich der Erkennung und Interaktion mit UI-Elementen, Maus- und Tastatursteuerung und grundlegendes Logging. White unterstützt hauptsächlich WinForms und WPF, wobei die Unterstützung für neuere Frameworks wie UWP begrenzt ist. White eignet sich gut für die Automatisierung von Desktop-Anwendungen, die auf diesen älteren Frameworks basieren. Trotz seiner Stabilität in diesen Anwendungsbereichen hat White Einschränkungen bei der Anpassung und Erweiterung, was die Automatisierung komplexerer und modernerer Anwendungen erschwert. Es ist weniger flexibel als FlaUI und kann bei der Handhabung dynamischer UI-Elemente an seine Grenzen stoßen.FlaUI punktet bei diesem Vergleich durch seine moderne Architektur, umfassende Unterstützung verschiedener UI-Frameworks und eine aktive Community, die eine robuste und flexible Lösung für die UI-Automatisierung bietet. White hingegen, obwohl funktional und nützlich in bestimmten Szenarien, hat im Lauf der Zeit an Aktualität und Unterstützung verloren. Entwickler, die eine zukunftssichere und gut unterstützte Automatisierungsbibliothek suchen, werden mit FlaUI wahrscheinlich besser bedient sein.

FlaUI versus TestComplete

TestComplete [5] ist ein umfassendes kommerzielles Tool zur Automatisierung von GUI-Tests, entwickelt von SmartBear. Es bietet Unterstützung für eine Vielzahl von Technologien und Plattformen, darunter Desktop-, Web- und Mobile-Anwendungen.TestComplete ermöglicht die Erstellung von automatisierten Tests durch Skripterstellung in verschiedenen Sprachen wie JavaScript, Python und VBScript sowie durch eine skriptlose Aufnahme- und Wiedergabefunktion. Zu den Hauptfunktionen gehören die Unterstützung für die parallele Testausführung, die Integration in CI/CD-Pipelines, umfangreiche Berichtsfunktionen und die Fähigkeit, mit verschiedenen Testmanagement-Tools zu interagieren.TestComplete unterstützt eine breite Palette von Technologien und Plattformen. Die Bibliothek kann für die Automatisierung von Desktop-Anwendungen (Windows), Web-Anwendungen (verschiedene Browser) und mobilen Anwendungen (iOS und Android) verwendet werden.Diese Vielseitigkeit macht es zu einer bevorzugten Wahl für Unternehmen, die Tests über verschiedene Plattformen hinweg konsolidieren möchten. TestComplete bietet Unterstützung für moderne Frameworks und Technologien, einschließlich React, Angular und .NET.TestComplete und FlaUI bieten jeweils einzigartige Vorteile für die UI-Automatisierung. TestComplete ist eine umfassende, kommerzielle Lösung mit Unterstützung für eine Vielzahl von Plattformen und Technologien, ideal für Unternehmen, die eine vielseitige und gut unterstützte Lösung benötigen. FlaUI hingegen ist eine spezialisierte, kostenfreie Open-Source-Bibliothek, die sich hervorragend für .NET-basierte Desktop-Anwendungen eignet und Entwicklern Flexibilität und Anpassungsfähigkeit bietet. Die Wahl zwischen den beiden hängt von den spezifischen Anforderungen, dem Budget und den bevorzugten Technologien des Anwenders ab.

FlaUI versus Ranorex

Ranorex [6] ist eine umfassende, kommerzielle Lösung für die Automatisierung von GUI-Tests, die sich durch einen breiten Funktionsumfang und umfangreiche Features auszeichnet. Es unterstützt die Automatisierung von Desktop-, Web- und mobilen Anwendungen. Ranorex bietet eine Aufnahme- und Wiedergabefunktion, die es ermöglicht, Tests ohne tiefgehende Programmierkenntnisse zu erstellen. Zusätzlich unterstützt Ranorex die Automatisierung mittels Skripting in C# und VB.NET. Zu den herausragenden Features von Ranorex gehören die Unterstützung für die parallele Testausführung, detaillierte Berichtsfunktionen, visuelle Testdesign-Tools und ein robustes Object-Repository zur Verwaltung von UI-Elementen. Ranorex bietet zudem umfassende Integrationen mit Testmanagement- und CI/CD-Tools.FlaUI erfordert im Vergleich zu Ranorex mehr technisches Wissen und Programmiererfahrung, da es keine Aufnahme- und Wiedergabefunktion bietet. Benutzer müssen mit C# vertraut sein und ein Verständnis für das UI Automation API haben, um effektiv mit FlaUI arbeiten zu können. Die Lernkurve ist daher steiler, aber für Entwickler, die eine tiefere Kontrolle über ihre Automatisierungsskripte benötigen, bietet FlaUI eine leistungsfähige und flexible Lösung. Die Dokumentation und Community-Ressourcen von FlaUI sind hilfreich, aber nicht so umfassend wie bei kommerziellen Tools wie Ranorex.

FlaUI versus CodedUI

CodedUI [7] ist ein automatisiertes UI-Testtool, das von Microsoft entwickelt wurde und tief in die Visual-Studio-Umgebung integriert ist. Es ermöglicht die Erstellung und Ausführung von UI-Tests für Desktop- und Webanwendungen.CodedUI unterstützt die Automatisierung von Interaktionen mit UI-Elementen, die Validierung von UI-Zuständen und die Erstellung von Tests mittels Aufnahme- und Wiedergabefunktionen. Zu den Hauptfunktionen gehören die Unterstützung für Rich-Client-Anwendungen (wie WinForms und WPF), die Integration mit Visual Studio für nahtlose Entwicklungs- und Debugging-Erlebnisse und die Nutzung des Microsoft UI Automation API. CodedUI eignet sich deshalb besonders für Teams, die stark in das Microsoft-Ökosystem integriert sind und die Vorteile der Visual-Studio-Integration nutzen möchten.Die Bibliothek CodedUI ist vollständig in Visual Studio integriert, was eine nahtlose Entwicklungs- und Debugging-Erfahrung bietet. Entwickler können CodedUI-Tests direkt innerhalb der Visual-Studio-Umgebung erstellen, ausführen und debuggen. Die enge Integration mit Visual Studio ermöglicht es, die gesamte Suite von Entwicklungswerkzeugen zu nutzen, einschließlich des Team Foundation Servers (TFS) und Azure DevOps. Diese Integration macht CodedUI zu einer attraktiven Option für Teams, die bereits Visual Studio verwenden und eine allumfassende Lösung für Entwicklung und Testen suchen.CodedUI war lange Zeit ein integraler Bestandteil des Microsoft-Ökosystems, aber Microsoft hat angekündigt, dass es keine weiteren Entwicklungen und nur noch begrenzte Unterstützung für CodedUI geben wird. Die offizielle Abkündigung bedeutet, dass Teams, die langfristige Investitionen in UI-Testautomatisierung planen, möglicherweise nach alternativen Lösungen suchen müssen. Die Community-Unterstützung für CodedUI nimmt ebenfalls ab, da sich die Entwickler auf neuere Tools und Technologien konzentrieren.Während CodedUI durch seine Integration in Visual Studio und seine umfassenden Funktionen attraktiv war, gibt es wegen der Einstellung der Weiterentwicklung keine Empfehlung dafür. FlaUI hingegen bietet eine flexible, anpassbare und zukunftssichere Lösung für die UI-Automatisierung mit einer aktiven Community und kontinuierlicher Entwicklung.

Fazit

FlaUI bietet zahlreiche Funktionen, um verschiedenste Anwendungen fernzusteuern. Die Basis durch UIA-Version 2 oder Version 3 ist stabil und bietet die Grundlagen, um das UI von Anwendungen anzusprechen. Zudem ist FlaUI flexibel, anpassungsfähig und kostenfrei. Im Vergleich zu anderen Bibliotheken und Tools wie TestStack.White, TestComplete, Ranorex und CodedUI zeigt sich, dass FlaUI einige herausragende Vorteile bietet, aber auch in bestimmten Bereichen Abstriche machen muss.Neben den Vorteilen hat FlaUI die Herausforderung, dass es eine steilere Lernkurve im Vergleich zu anderen Tools wie Ranorex aufweist. Zudem fokussiert sich FlaUI auf den Desktop und dort insbesondere auf .NET-Anwendungen. Wer Webseiten steuern möchte, muss sich anderweitig umsehen. Für Entwickler und Teams, die nach einer kosteneffizienten und anpassbaren Automatisierungslösung suchen, ist FlaUI eine hervorragende Wahl. Das Tool verdient sich daher ein „Sehr gut“ und eine Empfehlung, einen Blick auf die Bibliothek zu werfen.
Projektdateien herunterladen

Fussnoten

  1. Die Website zur UI Automation von Microsoft, http://www.dotnetpro.de/SL2410Frameworks1
  2. Das Repository zu FlaUI auf GitHub, http://www.dotnetpro.de/SL2410Frameworks2
  3. Die Website zur Accessibility Insights für Windows, http://www.dotnetpro.de/SL2410Frameworks3
  4. Das Repository zu TechStack.White, http://www.dotnetpro.de/SL2410Frameworks4
  5. Die Website zu TestComplete, http://www.dotnetpro.de/SL2410Frameworks5
  6. Die Website zu Ranorex, http://www.ranorex.com
  7. Die Hilfeseite zu CodedUI von Microsoft, http://www.dotnetpro.de/SL2410Frameworks6

Neueste Beiträge

DWX hakt nach: Wie stellt man Daten besonders lesbar dar?
Dass das Design von Websites maßgeblich für die Lesbarkeit der Inhalte verantwortlich ist, ist klar. Das gleiche gilt aber auch für die Aufbereitung von Daten für Berichte. Worauf besonders zu achten ist, erklären Dr. Ina Humpert und Dr. Julia Norget.
3 Minuten
27. Jun 2025
DWX hakt nach: Wie gestaltet man intuitive User Experiences?
DWX hakt nach: Wie gestaltet man intuitive User Experiences? Intuitive Bedienbarkeit klingt gut – doch wie gelingt sie in der Praxis? UX-Expertin Vicky Pirker verrät auf der Developer Week, worauf es wirklich ankommt. Hier gibt sie vorab einen Einblick in ihre Session.
4 Minuten
27. Jun 2025
„Sieh die KI als Juniorentwickler“
CTO Christian Weyer fühlt sich jung wie schon lange nicht mehr. Woran das liegt und warum er keine Angst um seinen Job hat, erzählt er im dotnetpro-Interview.
15 Minuten
27. Jun 2025
Miscellaneous

Das könnte Dich auch interessieren

UIs für Linux - Bedienoberflächen entwickeln mithilfe von C#, .NET und Avalonia
Es gibt viele UI-Frameworks für .NET, doch nur sehr wenige davon unterstützen Linux. Avalonia schafft als etabliertes Open-Source-Projekt Abhilfe.
16 Minuten
16. Jun 2025
Mythos Motivation - Teamentwicklung
Entwickler bringen Arbeitsfreude und Engagement meist schon von Haus aus mit. Diesen inneren Antrieb zu erhalten sollte für Führungskräfte im Fokus stehen.
13 Minuten
19. Jan 2017
Evolutionäres Prototyping von Business-Apps - Low Code/No Code und KI mit Power Apps
Microsoft baut Power Apps zunehmend mit Features aus, um die Low-Code-/No-Code-Welt mit der KI und der professionellen Programmierung zu verbinden.
19 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige