Skip to content

Commit 7b2cdb8

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents bd1d8ec + 1d6629c commit 7b2cdb8

41 files changed

Lines changed: 1565 additions & 554 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

19_Testen.md

Lines changed: 259 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
author: Sebastian Zug, Galina Rudolf & André Dietrich
44
email: sebastian.zug@informatik.tu-freiberg.de
5-
version: 1.0.10
5+
version: 1.0.11
66
language: de
77
narrator: Deutsch Female
88
comment: Softwarefehler, Testen zur Qualitätssicherung, Planung von Tests, Konzepte und Umsetzung in dotnet
@@ -109,7 +109,7 @@ Betrieb und Wartung:
109109
+ Die Schulung der Anwender wird vernachlässigt.
110110
+ Das Konfigurationsmanagement ist unzureichend.
111111

112-
<!--
112+
<!--https://raw.githubusercontent.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/refs/heads/master/19_Testen.md
113113
style="width: 100%; max-width: 560px; display: block; margin-left: auto; margin-right: auto;"
114114
-->
115115
````````````
@@ -791,3 +791,260 @@ reportgenerator "-reports:.coverage/**/*.cobertura.xml" "-targetdir:.coverage-re
791791
Das Argument "XPlat Code Coverage" bezieht sich auf das Zwischenformat der Darstellung. Das `./.coverage` dient zur Angabe des Verzeichnisses, in dem die Ergebnisse gespeichert werden sollen. Wenn keines angegeben wird, wird standardmäßig ein TestResults-Verzeichnis innerhalb jedes Projekts verwendet. `reportgenerator` erzeugt dann die entsprechende html-Repräsentation.
792792

793793
![instruction-set](./img/16_Testen/ReportGenerator.png)
794+
795+
796+
> Im Projektordner finden Sie die gesamte Testimplementierung. Diese wurde um eine Python Applikation erweitert, die eine Sprachübergreifende Nutzung einer Csharp Bibliothek illustriert.
797+
798+
## Fazit
799+
800+
> Testen auf Modulebene - reicht das aus?
801+
802+
Testen auf Modulebene ist ein wichtiger Bestandteil der Softwareentwicklung, aber es ist nicht ausreichend, um die Qualität eines gesamten Systems zu gewährleisten. Es deckt nur die kleinsten Einheiten ab und stellt sicher, dass diese korrekt funktionieren. Allerdings können Fehler in der Interaktion zwischen Modulen oder in der Systemintegration unentdeckt bleiben.
803+
804+
805+
## Erweiterung
806+
807+
| Testart | Fokus | Isolation | Beispiel |
808+
| ---------------------- | ---------------- | ----------- | --------------------------------- |
809+
| Unit-Test | Methode/Funktion | vollständig | `Addiere(int a, int b)` |
810+
| Modul-/Komponententest | Klasse/Modul | teilweise | `Warenkorb.AddArtikel()` |
811+
| Integrationstest | mehrere Module | gering | Bestellung -> Lager -> Versand |
812+
| Systemtest | gesamte App | keine | App starten und Bestellung testen |
813+
814+
### Testen auf Modulebene
815+
816+
{{0-1}}
817+
****************************************************************
818+
819+
Modul oder Komponententests sind Tests, die sich auf einzelne Module oder Komponenten einer Software konzentrieren. Sie überprüfen die Funktionalität und das Verhalten dieser Module isoliert von anderen Teilen des Systems.
820+
821+
```csharp
822+
using Xunit;
823+
824+
public class WarenkorbTests {
825+
[Fact]
826+
public void Test_Gesamtpreis_fuer_mehrere_Artikel() {
827+
// Arrange
828+
var korb = new Warenkorb();
829+
korb.Hinzufügen(new Artikel { Name = "Buch", Preis = 10.0m });
830+
korb.Hinzufügen(new Artikel { Name = "Stift", Preis = 2.0m });
831+
832+
// Act
833+
var gesamt = korb.Gesamtpreis();
834+
835+
// Assert
836+
Assert.Equal(12.0m, gesamt);
837+
}
838+
}
839+
```
840+
841+
****************************************************************
842+
843+
{{1-2}}
844+
****************************************************************
845+
846+
847+
In der realen Software bestehen viele Klassen aus Abhängigkeiten zu anderen Komponenten – z. B. Datenbanken, externe Dienste oder Services.
848+
849+
**Mocks** sind Test-Doubles, mit denen du diese Abhängigkeiten im Test ersetzen kannst, um:
850+
851+
- das Verhalten der Komponente isoliert zu testen
852+
- kontrollierte Rückgaben zu simulieren
853+
- Seiteneffekte zu vermeiden
854+
855+
856+
__Warum ist Mocking wichtig?__
857+
858+
Ohne Mocks würdest du in jedem Testfall:
859+
860+
- eine echte Datenbank ansprechen
861+
- eine E-Mail versenden
862+
- einen Webservice kontaktieren
863+
864+
Das macht Tests langsam, fehleranfällig und unzuverlässig.
865+
866+
__Best Practices beim Mocking__
867+
868+
- Mocke nur explizite Abhängigkeiten (nicht alles!)
869+
- Nutze Interfaces oder abstrakte Klassen als Testanker
870+
- Verwende `.Setup(...)` nur für erwartetes Verhalten
871+
- Nutze `.Verify(...)` zur Kontrolle von Aufrufen (z. B. ob ein E-Mail-Versand ausgelöst wurde)
872+
873+
****************************************************************
874+
875+
{{2-3}}
876+
****************************************************************
877+
878+
Produktionscode:
879+
880+
```csharp
881+
public interface IPreisDienst {
882+
decimal GibPreis(string artikelId);
883+
}
884+
885+
public class Kasse {
886+
private readonly IPreisDienst _preisDienst;
887+
888+
public Kasse(IPreisDienst preisDienst) {
889+
_preisDienst = preisDienst;
890+
}
891+
892+
public decimal BerechneGesamtpreis(string artikelId, int menge) {
893+
var einzelpreis = _preisDienst.GibPreis(artikelId);
894+
return einzelpreis * menge;
895+
}
896+
}
897+
```
898+
899+
Testcode mit Mocking:
900+
901+
```csharp
902+
using Moq;
903+
using Xunit;
904+
905+
public class KasseTests {
906+
[Fact]
907+
public void BerechneGesamtpreis_mit_MockDienst() {
908+
// Arrange
909+
var mockDienst = new Mock<IPreisDienst>();
910+
mockDienst.Setup(d => d.GibPreis("A1")).Returns(10.0m);
911+
912+
var kasse = new Kasse(mockDienst.Object);
913+
914+
// Act
915+
var gesamt = kasse.BerechneGesamtpreis("A1", 3);
916+
917+
// Assert
918+
Assert.Equal(30.0m, gesamt);
919+
}
920+
}
921+
```
922+
923+
***************************************************************
924+
925+
### Integrationstests
926+
927+
Ein **Integrationstest** prüft das **Zusammenspiel mehrerer Module oder Klassen**, z. B.:
928+
929+
- Controller ↔ Service ↔ Datenbank
930+
- UI ↔ Backend ↔ API
931+
- Repository ↔ Domain-Logik
932+
933+
> Ziel ist es, **Schnittstellenfehler** und **Zusammenarbeitsprobleme** zu erkennen – bevor das System als Ganzes getestet wird.
934+
935+
Produktionscode:
936+
937+
```csharp
938+
// Domainmodell
939+
public class Artikel {
940+
public int Id { get; set; }
941+
public string Name { get; set; }
942+
public decimal Preis { get; set; }
943+
}
944+
945+
// Repository
946+
public class ArtikelRepository {
947+
private readonly DbContext _ctx;
948+
public ArtikelRepository(DbContext ctx) => _ctx = ctx;
949+
950+
public void Speichern(Artikel a) {
951+
_ctx.Add(a);
952+
_ctx.SaveChanges();
953+
}
954+
955+
public Artikel? Finde(int id) => _ctx.Set<Artikel>().Find(id);
956+
}
957+
```
958+
959+
Testcode mit Mocking:
960+
961+
```csharp
962+
using Xunit;
963+
using Microsoft.EntityFrameworkCore;
964+
965+
public class ArtikelRepositoryTests {
966+
[Fact]
967+
public void Speichern_und_Lesen_von_Artikeln() {
968+
// Arrange: In-Memory-Kontext
969+
var options = new DbContextOptionsBuilder<DbContext>()
970+
.UseInMemoryDatabase("TestDB")
971+
.Options;
972+
973+
using var ctx = new DbContext(options);
974+
var repo = new ArtikelRepository(ctx);
975+
var artikel = new Artikel { Name = "Test", Preis = 5.0m };
976+
977+
// Act
978+
repo.Speichern(artikel);
979+
var gelesen = repo.Finde(artikel.Id);
980+
981+
// Assert
982+
Assert.NotNull(gelesen);
983+
Assert.Equal("Test", gelesen?.Name);
984+
}
985+
}
986+
```
987+
988+
> Anstatt einen echten Datenbankserver zu verwenden, nutzen wir eine **In-Memory-Datenbank** für die Tests. Diese ermöglicht aber auch wesentlich konkrete Umsetzungen als die Mock-Objekte, da sie die tatsächliche Datenbank-Logik "simuliert".
989+
990+
### Testen auf Systemebene
991+
992+
Ein **Systemtest** überprüft das **gesamte Systemverhalten** aus Sicht des Endnutzers.
993+
Dabei wird die gesamte Anwendung als Black Box getestet – **alle Komponenten, Module und Schnittstellen** sind integriert.
994+
995+
> Ziel: Sicherstellen, dass das System als Ganzes die Anforderungen erfüllt.
996+
997+
---
998+
999+
### Abgrenzung zu anderen Tests
1000+
1001+
| Testart | Fokus | Perspektive |
1002+
| ---------------- | ----------------------------- | --------------- |
1003+
| Unittest | Einzelne Methode | Entwickler |
1004+
| Komponententest | Klasse/Modul | Entwickler |
1005+
| Integrationstest | Zusammenspiel mehrerer Module | Entwickler |
1006+
| **Systemtest** | Gesamtsystem | **Nutzer / Tester** |
1007+
1008+
1009+
### Eigenschaften von Systemtests
1010+
1011+
- Arbeiten mit **realen oder simulierten Datenbanken, Schnittstellen, UI**
1012+
- Testen **End-to-End-Szenarien** (z. B. Anmeldung, Bestellung, Zahlung)
1013+
- Häufig **automatisiert** mit Tools wie Selenium, Playwright oder TestServer
1014+
- Können auch **manuell** durchgeführt werden (z. B. nach Checklisten)
1015+
1016+
1017+
## Vergleich
1018+
1019+
| Kriterium | **Methodentest** (Unit Test) | **Komponententest** | **Integrationstest** | **Systemtest** |
1020+
| ----------------------- | ---------------------------------- | ---------------------------------------------- | -------------------------------------------- | ------------------------------------------- |
1021+
| **Testobjekt** | Einzelne Methode oder Funktion | Klasse oder Modul mit internen Abhängigkeiten | Zusammenspiel mehrerer Komponenten/Module | Gesamtsystem (End-to-End) |
1022+
| **Ziel** | Korrektheit der kleinsten Einheit | Zusammenarbeit mehrerer Funktionen | Schnittstellen und Zusammenarbeit testen | Verhalten des Systems aus Sicht des Nutzers |
1023+
| **Abhängigkeiten** | Werden meist gemockt oder isoliert | Können teilweise eingebunden oder ersetzt sein | Echte Implementierungen (z. B. DB, Services) | Realitätsnahe, echte Umgebung |
1024+
| **Beispiel** | `CalculateSum(int a, int b)` | `UserService` mit `EmailService` | `UserController``UserRepository` (mit DB) | REST-API ↔ Datenbank ↔ Frontend |
1025+
| **Tools** | xUnit, NUnit | xUnit + Moq/Fakes | xUnit + InMemory DB / Testcontainers | Selenium, Postman, TestServer |
1026+
| **Laufzeit** | Sehr kurz | Mittel | Mittel bis lang | Lang |
1027+
| **Testgeschwindigkeit** | 🔵 Schnell | 🟡 Mittel | 🟡 Mittel | 🔴 Langsam |
1028+
| **Zuverlässigkeit** | Hoch (bei guter Isolation) | Mittel (Abhängigkeiten können stören) | Mittel (mehr Fehlerquellen möglich) | Niedriger (viele beteiligte Komponenten) |
1029+
| **Fehlersuche** | Sehr präzise | Eingrenzbar | Eingrenzbar mit Fokus auf Schnittstellen | Schwieriger (viele beteiligte Komponenten) |
1030+
| **CI/CD-Einsatz** | Immer | Häufig | Häufig / nach jedem Build | Selektiv / nachts |
1031+
1032+
Andere Darstellung
1033+
1034+
```ascii
1035+
+---------------------------+
1036+
| Systemtests | 🔴 Langsam, teuer, realistisch
1037+
+---------------------------+
1038+
+-----------------------+
1039+
| Integrationstests | 🟡 Echte Zusammenarbeit prüfen
1040+
+-----------------------+
1041+
+-------------------+
1042+
| Komponententests | 🟡 Module mit Abhängigkeiten
1043+
+-------------------+
1044+
+---------------+
1045+
| Unittests | 🔵 Schnell, stabil, viele
1046+
+---------------+
1047+
1048+
> 🔺 Je weiter oben, desto aufwändiger
1049+
> 🔻 Je weiter unten, desto mehr Tests sollten existieren .
1050+
```

20_ContinuousIntegration.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ print("Phone Numbers:")
277277
for phone in data['person']['phoneNumbers']:
278278
print(f" {phone['type']}: {phone['number']}")
279279
```
280-
@LIA.eval(`["data.csv", "main.py"]`, `none`, `python3 main.py`)
280+
@LIA.eval(`["data.yaml", "main.py"]`, `none`, `python3 main.py`)
281281

282282

283283
## Continuous integration (CI)
@@ -347,18 +347,27 @@ Techniken des CD sind:
347347
+ Blue-Green Deployment (harter Wechsel zwischen zwei Produktionsumgebung)
348348
+ Canary Deployment (Selektives Ausrollen der neuen Version)
349349

350-
## DevOps
350+
## Einordnung
351351

352-
DevOps betrachtet den gesamten Softwareentwicklungs- und Bereitstellungsprozess, von der Planung und Codierung bis zum Testen, Bereitstellen und Betrieb.
352+
DevOps (eine Kombination aus Development und Operations) ist ein ganzheitlicher Ansatz, der den gesamten Lebenszyklus von Software betrachtet – von der Planung und Entwicklung über das Testen, die Bereitstellung bis hin zum Betrieb und der Überwachung von Anwendungen im Produktivsystem.
353353

354-
+ DevOps ist ein umfassenderer Ansatz, der die Kultur, Praktiken und Werkzeuge umfasst, um die Zusammenarbeit zwischen Entwicklungs- und Betriebsteams zu verbessern und die Softwarebereitstellung zu optimieren.
355-
+ CI/CD sind spezifische Praktiken innerhalb von DevOps, die sich auf die Automatisierung der Integration und Bereitstellung von Codeänderungen konzentrieren.
354+
Ziel von DevOps ist es, die Zusammenarbeit zwischen Entwicklungs- und Betriebsteams zu verbessern. Historisch waren diese beiden Bereiche oft getrennt: Entwickler wollten neue Funktionen möglichst schnell implementieren, während das Betriebsteam auf Stabilität und Sicherheit achtete – oft mit widersprüchlichen Zielen. DevOps überbrückt diese Kluft, indem es eine gemeinsame Verantwortung für den gesamten Prozess schafft.
356355

356+
Dabei spielen Kultur, Prozesse und Werkzeuge eine zentrale Rolle:
357+
358+
+ Kultureller Wandel: DevOps fördert eine offene Kommunikationskultur, gegenseitiges Vertrauen und geteilte Verantwortlichkeit. Fehler werden nicht als Versagen, sondern als Chance zur Verbesserung gesehen.
359+
+ Prozesse: DevOps strebt kontinuierliche Verbesserungen durch kurze Feedbackzyklen, häufige Releases und automatisierte Qualitätssicherung an.
360+
+ Werkzeuge: Die Nutzung von Automatisierungstools zur Codeintegration, Testausführung, Infrastrukturverwaltung und Überwachung ist essenziell, um manuelle Fehler zu reduzieren und schnell auf Änderungen reagieren zu können.
361+
362+
> Continuous Integration (CI) und Continuous Delivery bzw. Deployment (CD) sind zentrale Bausteine innerhalb von DevOps.
357363
358364
## CI Umsetzung mit GitHub
359365

360366
{{0-1}}
361367
*******************************************************************************
368+
369+
> Achtung: Wir gehen hier hauptsächlich auf GitHub-Actions ein. Die Konzepte sind auf andere Git-Repositories wie Gitlab oder Bitbucket übertragbar. Die Syntax unterscheidet sich allerdings.
370+
362371
Welche Elemente machen somit eine CI Pipeline aus:
363372

364373
* **Wann** (Trigger) soll

0 commit comments

Comments
 (0)