Automatische Integrations- und Systemtests mit Testcontainers

Testcontainers

Im letzten Artikel [1] haben wir uns mit automatischen Integrationstests mit ASP.NET Core beschäftigt. In diesem Artikel baue ich darauf auf und ergänze das Thema um eine sehr spannende Variante zum Mocking fremder Services. Die meisten Entwickler kennen das Problem. Sobald man auf der Integrations- oder Systemtestebene testen möchte, muss man sich über die Abhängigkeiten zu anderen Services Gedanken machen. Das fängt bereits bei der Datenbank an und hört dort leider nicht auf. Es geht i. d. R. auch um andere Services, die während des Testens benötigt werden. Zur Lösung des Problems gibt es grundsätzlich zwei Varianten: Man bindet externe Services während des Tests an oder man versteckt sie hinter einer Schnittstelle und baut einen Mock darum. Die erste Variante ist zwar realitätsnäher, hat aber einige gewichtige Nachteile. So ist die Laufzeit von Tests länger, man hängt vom Status eines externen Service ab und mehrere, konkurrierend laufende Tests können zum Problem werden. Mit Testcontainers können wir die meisten dieser Nachteile Streichen. Wie genau erkläre ich in diesem Artikel.

Weiterlesen …

Automatische Integrationstests mit ASP.NET Core

Integrationstests

Softwaretest ist ein Thema, was jeden Softwareentwickler stets begleitet. Wenn es um Testautomatisierung geht, erhalten wir dazu ein breites Set an Werkzeugen in die Hand gedrückt. Das geht bei Testframeworks wie xUnit los und geht über die Integration solcher Frameworks in moderne IDEs wie Visual Studio und Rider weiter. In diesem Beitrag möchte ich mir eines dieser Werkzeuge herauspicken und ins Rampenlicht rücken: Es geht um Integrationstests mit ASP.NET Core. Warum? Genau diese Art von Tests hat einen sicheren Platz in meinem Werkzeugkoffer eingenommen. Es passt sehr gut zu der Art, wie ich Testautomatisierung und das Thema Testpyramide / Testdiamant schon seit sehr langer Zeit sehe (mehr dazu unter [1]). Ich setze bei Testautomatisierung i. d. R. mehr auf einen sog. “Testdiamanten”, als auf eine “Testpyramide”. Dafür gibt es viele Gründe. Ein wichtiger ist, dass damit das Verhalten einer Softwarekomponente auf einer höheren Ebene getestet und damit festgezogen wird. So viel möchte ich jetzt aber nicht über die Gründe schreiben, sondern jetzt zum Thema des Artikels kommen.

Weiterlesen …

Protobuf Nachrichten kompatibel erweitern

Kommunikation

Im letzten Blogartikel habe ich Protobuf als Serialisierungsformat vorgestellt [1]. In diesem Artikel möchte ich mich mit einem Thema beschäftigen, auf das man im Laufe eines Projekts früher oder später kommt: Wie erweitere ich eine Protobuf Nachricht so, dass die Änderung kompatibel zur vorherigen Version der Nachricht bleibt? Diese Frage taucht typischerweise dann auf, wenn eine zu ändernde Nachricht zwischen zwei oder mehr Services ausgetauscht wird, diese Services bei einem Update aber nicht gleichzeitig aktualisiert werden (können). Nehmen wir ein einfaches Beispiel: Ich möchte in neues Feld in einem Nachrichtentyp hinzufügen. Zunächst mache ich das am Service, welcher die Nachricht sendet und etwas später mache ich das bei den empfangenden Services. Geht das einfach so? Diese und weitere ähnliche Fragen möchte ich mit diesem Artikel beantworten. Ich beziehe mich bei den Beispielen ausschließlich auf C# und die Protobuf Implementierung im Paket Google.Protobuf.

Weiterlesen …

Protobuf in C# serialisieren und deserialisieren

Protobuf C#

Es gibt eine lange Liste von Formaten, welche für die Serialisierung und Deserialisierung von .NET Objekten verwendet werden kann. Xml und Json sind dabei lediglich die populärsten Vertreter. In diesem Artikel möchte ich mich mit Protobuf (oder ausgeschrieben “Protocol Buffers”) beschäftigen. Protobuf ist ein Format von Google. Es ist auf Performance und möglichst wenig Platzverbrauch ausgelegt. Zudem gibt es Unterstützung für viele verschiedene Programmiersprachen – C# ist nur eine davon. Protobuf lässt sich mit den Bibliotheken von Google in Java, Python, Objective-C, C++, Kotlin, Dart, Go, Ruby, PHP und natürlich C# verwenden. Es findet auch im Protokoll gRPC Verwendung. Letzteres ist einer der Gründe, warum ich mich mit Protobuf mehr in der Tiefe beschäftigt habe. Schließlich interessiert mich nicht nur die Serialisierung selbst oder Sachen wie die Performance, sondern auch wie mit Kompatibilitätsthemen (neue Felder, umbenannte Felder, etc.) umgegangen wird. In diesem Artikel schauen wir uns diese Themen anhand zweier alternativer Bibliotheken an. Diese sind Google.Protobuf von Google und protobuf-net von Marc Gravell.

Weiterlesen …

Testautomatisierung mit Avalonia

Testautomatisierung mit Avalonia

Testautomatisierung auf UI Ebene ist häufig nicht so einfach zu erreichen. Grund dafür können technische Fragestellungen sein. So gilt es, auf irgendeine Art das Rendering des UI-Frameworks abzubilden. Ebenso gilt es, mögliche Usereingaben zu emulieren oder Eingabeelemente an der UI zu identifizieren. Auch zeitliche Aspekte spielen mit rein, so ist ein “Warte eine Sekunde…” in einem automatisierten Test i. d. R. eine eher schlechte Idee. Doch es gibt auch Herausforderungen, die aus den Testfällen selbst entstehen. Versucht man etwa, ein Drag-Drop Verhalten automatisiert zu testen, beißt man sich dabei schon mal gerne die Zähne aus. Ich persönlich versuche UI Tests daher auf einem niedrigen Level zu halten, setze sie also primär für einfach zu überblickende Geradeausfälle ein. Mit Avalonia habe ich UI Tests zuletzt bei meinem Nuget-Paket RolandK.AvaloniaExtensions [1] eingesetzt. Hier ging es mir darum, dass die dort definierten Basisklassen und Features wie die Dependency Injection einwandfrei in einer Avalonia Applikation funktionieren.

Weiterlesen …

Avalonia FluentTheme zur Laufzeit wechseln

Avalonia Theme Switch

Viele moderne Applikationen bieten neben einer ansprechenden UI auch den Wechsel zwischen verschiedenen Themes an. Für gewöhnlich wird zumindest zwischen Hell und Dunkel unterschieden. Gleiches gilt für das Betriebssystem selbst – Windows und macOS bieten dem User jeweils die Wahl zwischen Hell und Dunkel. Auch Avalonia bietet mit dem FluentTheme seit Version 0.10 einen sehr einfachen Weg an, zwischen hellen und dunklen Modus zu unterscheiden. Typischerweise wird das FluentTheme in der App.xaml angegeben und bekommt als Mode entweder “Light” oder “Dark”. In diesem Artikel wollen wir uns damit beschäftigen, wie diese Einstellung zur Laufzeit der Applikation verändert werden kann. Weiterhin schauen wir uns an, wie man unter Windows den aktuell konfigurierten Theme herausbekommt und sogar auf Änderung des aktuellen Theme reagieren kann.

Weiterlesen …

Avalonia Applikationen übersetzen

Avalonia Applikationen übersetzen

In den letzten Monaten habe ich vermehrt Artikel über das Cross-Platform Framework Avalonia geschrieben. Für mich persönlich hat sich das Framework mittlerweile zum Standard für Desktop-Applikationen entwickelt. Es kann fast alles, was man braucht und läuft auf allen gängigen Desktop Plattformen (Windows, macOS, Linux) stabil. In diesem Artikel möchte ich mich mit einem Thema beschäftigen, auf das die meisten Softwareentwickler bei UIs irgendwann stoßen: Applikationen in andere Sprachen übersetzen. Auch wenn man nicht den akuten Bedarf hat, so sollte man UIs möglichst von vorne herein darauf vorbereiten, dass sie übersetzbar sind. Übersetzung im Nachhinein einzubauen kann häufig sehr schwierig sein. Insbesondere, wenn Daten von außen bereits behaftet mit einer bestimmten Sprache in der eigenen Applikation ankommen.

Weiterlesen …

Yaml Dateien mit C# parsen

Yaml Parsing

Es gibt eine lange Liste von verbreiteten Markup-Formaten. Xml und Json sind dabei den allermeisten Entwicklern ein Begriff. Auch Yaml ist ein Format, welches nicht zuletzt durch den Einsatz bei Kubernetes oder anderen bekannten Applikationen eine größere Verbreitung genießt. Yaml wirkt auf den ersten Blick wie ein “Json ohne Klammern”. Das habe ich selbst tatsächlich auch lange so angenommen. Beschäftigt man sich etwas tiefer im Detail mit Yaml, so wird man aber schnell eines Besseren belehrt. Yaml bietet mehrere Features und hat etwa bei der Ermittlung der Datentypen ein mehr oder weniger komplexes Regelwerk. Aber warum überhaupt Yaml, wenn man doch auch Json einsetzen könnte? Yaml-Dateien könnten leichter durch einen Menschen geschrieben und gelesen werden. Aus diesem Grund wird es gerne für Konfigurationsdateien verwendet – so wie etwa bei Kubernetes. Somit kann es auch für C# Entwickler sinnvoll sein, anstelle von Json oder Xml eben Yaml für Konfigurationsdateien zu verwenden. Aus diesem Grund möchte ich mich in diesem Artikel mit dem Parsen von Yaml Dateien mit C# beschäftigen.

Weiterlesen …

Typisierten HttpClient mit NSwag generieren

NSwag-Codegenerierung

Fremde WEB-APIs anzusprechen ist längst eine Standardaufgabe für viele C# / .Net Entwickler. Einige folgen streng den Prinzipien von REST, andere wiederum nur grob. Als Gemeinsamkeit haben sie, dass die API über eine Swagger-Datei dokumentiert wird. Swagger-Dateien beschreiben alle zur Verfügung stehenden Endpunkte zusammen mit den Datenobjekten, welche zum Dienst und zurück zum Client übertragen werden. Daneben gibt es noch weitere Informationen, etwa zu möglichen Fehlern oder zu Gültigkeitsbereichen einzelner Felder. In den letzten Jahren habe ich mehrere Projekte gesehen, welche die Swagger-Dokumentation als Basis für einen eigenen, typisierten HttpClient verwenden. Der typisierte HttpClient wurde dabei aber meist von Hand programmiert. Das muss nicht immer so sein. Mit NSwag [1] etwa steht ein Werkzeug zur Verfügung, mit dessen Hilfe ein typisierter HttpClient generiert werden kann. In diesem Artikel möchte ich das anhand einer ASP.Net Core Blazor Applikation zeigen.

Weiterlesen …

Texture sampling in SeeingSharp 2

Texture sampling

In den letzten Tagen hatte ich wieder Zeit, an der 3D-Engine SeeingSharp 2 weiterzuarbeiten. Diesmal ging es darum, allgemein das Arbeiten mit Texturen zu verbessern. Genauer geht es um das Texture sampling. Texture sampling bezeichnet den Prozess, wie Farbinformationen aus Texturen gelesen werden. Direct3D bietet hierbei eine lange Liste von Einstellungen. So kann etwa beeinflusst werden, nach welcher Logik Texturen auf einer Fläche gekachelt werden sollen. Auch die Art, wie die Farben zweier benachbarter Pixel auf einer Textur vermischt werden, kann konfiguriert werden. Letzteres ist dann relevant, wenn eine Textur am Monitor mehr oder weniger Pixel beansprucht, als in der Textur selbst zur Verfügung stehen. Insgesamt hat SeeingSharp 2 bis jetzt nur ein Standard-Set an Einstellungen mit Anisotroper Filterung [1] unterstützt. Passt dieses Standard-Set nicht, so hatte man bis dato keine Möglichkeit, das Texture sampling zu beeinflussen.

Weiterlesen …