https://github.com/HerrLoesch/DDC2016
Zeit
Produktivität
Entwicklung
Weiter-
entwicklung
Weiter-
entwicklung
Weiter-
entwicklung
Stabilisierung
Optimierung
Sanierung
Stabilisierung
Stabilisierung
Optimierung
t in Jahren
Speichern Gespeichert
Benutzersicht
Benutzersicht Architektursicht
Speichern Anbindung UI
Anbindung
Persistenz
Geschäftslogik DB
Extern
System-Tests
Benutzersicht Architektursicht
Speichern Anbindung UI
Anbindung
Persistenz
Geschäftslogik DB
Extern
System-Tests
Systemtest
Integrationstest
Unit Test
Benutzersicht Architektursicht
Speichern Anbindung UI
Anbindung
Persistenz
Geschäftslogik DB
Extern
System-Tests
Unit-Tests
Benutzersicht Entwicklersicht
Speichern
Datenvali-
dierung
Fehlerbe-
handlung
Validierungs-
regeln
Speichervor-
gang
Zurücksetzen
bei Fehler
Fehler-
ausschrift
Validator
Unit-Tests
System-Tests
Eventhandler
DB
Datenbank-
anbindung
DS
Extern
Test
Implementierung
Refaktorisierung
DEMO
Systemtest
Integrationstest
Unit Test
Ausführungsgeschwindigkeit
Granularität
Systemtest
Integrationstest
Unit Test
Ausführungsgeschwindigkeit
Granularität
Änderungstoleranz
Abstraktion
UI
Business Layer
Data/Service Layer
O/R Mapper
UI
Business Layer
Data/Service Layer
UI
F
r
a
m
e
w
o
r
k
s
UI
Business Layer
Data/Service Layer
O/R Mapper
Unit tests run fast. If they don't run fast, they aren't unit tests. Other kinds
of tests offen masquerade as unit tests. A test is not a unit test if:
1. It talks to a database.
2. It communicates across a network.
3. It touches the file system.
4. You have to do special things to your environment (such as editing
configuration files) to run it.
Tests that do these things aren't bad. Often they are worth writing, and you
generally will write them in unit test harnesses. However, it is important to
be able to separate them from true unit tests so that you can keep a set of
tests that you can runfast whenever you make changes.
Benutzersicht Entwicklersicht
Speichern
Datenvali-
dierung
Fehlerbe-
handlung
Validierungs-
regeln
Speichervor-
gang
Zurücksetzen
bei Fehler
Fehler-
ausschrift
Validator
Unit-Tests
System-Tests
Eventhandler
DB
Datenbank-
anbindung
DS
Extern
Benutzersicht Entwicklersicht
Speichern
Datenvali-
dierung
Fehlerbe-
handlung
Validierungs-
regeln
Speichervor-
gang
Zurücksetzen
bei Fehler
Fehler-
ausschrift
Validator
Unit-Tests
System-Tests
Eventhandler
DB
Datenbank-
anbindung
DS
Extern
hohe Ergebnisgenauigkeit
Geringe Geschwindigkeit
je Test
Hohe Testanzahl
Geringer (Anfangs)aufwand
Hohe Ausführungsgeschwindigkeit
je Test
Geringe Testanzahl
Hoher (Anfangs)aufwand
Geringe Ergebnisgenauigkeit
Quelle: http://fabiopereira.me/blog/2012/03/18/introducing-depth-of-test-dot/
A B Xb
UI ViewModel
User-
Manager
Repository
Settings-
Manager
XIViewModel
UI ViewModel
User-
Manager
Repository
Settings-
Manager
Hashing
Logik
Value
Converter
IViewModel
Klassentest
Klassentest
Komponententest
ViewModel Repository
Data
Mapping
Data
Validation
Database
Context
Mapper
Value
Converter
IRepository
ViewModel Repository
Data
Mapping
Data
Validation
Database
Context
Mapper
Value
Converter
IRepository
Klassentest
Klassentest
Komponententest
System
Integrations-
test
Komponententest
Klassentests
Unit-Tests
Systemtest Test
Implementierung
Refaktorisierung
UIUI
BLBL
DADA
UI
BL Testdouble
Testdouble
BL BL
DADA
UI
BL BL
DA DA
DEMO
Problem
verstehen
Grobdesign
(„Architektur
Vision“)
Automatisierung
• Build
• Deployment
• End-To-End Tests
Produkt-
inkrement
Produkt
Release
System
Integrations-
test
Komponententest
Klassentests
Unit-Tests
Systemtest
Integrationstest
Komponententests
Klassentests
Systemtest
Integrationstest
Komponententests
Klassentests
Systemtest
Integrationstest
Komponententests
Klassentests
NUnit
xUnit.Net
MBUnit
MS Test
Smart Unit Tests
Systemtest
Integrationstest
Komponententests
Klassentests
NUnit
xUnit.Net
MBUnit
MS Test
MSpec
NSpec
SpecsFor
DynamicSpecs
public class When_no_data_is_entered_for_person
{
static Person sut;
Establish context = () => sut = new Person();
Because of = () => { /* nothing todo because we simply don't set any data */ };
It should_provide_an_error_text_for_BirthDate = () => sut["BirthDate"].ShouldNotBeEmpty();
It should_provide_an_error_text_for_FirstName = () => sut["FirstName"].ShouldNotBeEmpty();
It should_provide_an_error_text_for_LastName = () => sut["LastName"].ShouldNotBeEmpty();
}
Systemtest
Integrationstest
Komponententests
Klassentests
MSpec
NSpec
SpecsFor
DynamicSpecs
Specflow
Specflow
Gherkin
MS Test
XUnit.Net
NUnit
Mspec
… XUnit
UI Testing
Framework
Silenium
WatiN
Coded UI Tests
White
…
Given
When
Then
C#
Systemtest
Integrationstest
Komponententests
Klassentests
MSpec
NSpec
SpecsFor
DynamicSpecs
Specflow
Vertrauen
Aufwand
Feedback
Quelle: Dr. Elmar Jürgens, CQSE
4
3
2
1
Keine Defizite
Keine Defizite in geändertem Code
Keine neuen Defizite
Egal
Pragmatismus Overengineering
CI Umgebung für .Net Projekte.
+ Sehr einfach und übersichtlich.
+ Für Opensource kostenlos.
+ Gute Übersicht über die Ergebnisse und den
Verlauf.
+ Gute Zusammenarbeit mit Github.
o Geringe Anpassungmöglichkeiten.
- Ausführung und Dokumentation
automatisierter Tests eher rudimentär.
Beliebtester Hostingdienst für Opensource
Projekte auf Basis von Git.
+ Sehr große Community.
+ Für Opensource kostenlos.
+ Wird von vielen Diensten unterstützt.
o Private Repositories kostenpflichtig.
- UI ist bedingt nutzerfreundlich.
Vergleichsweise neue GUI für Git die versucht
andere Wege der Darstellung zu gehen.
+ Plattformunabhängig
+ Gute Abbildung der gängigen Arbeitsabläufe.
+ Auch komplexe Aufgaben können über die UI
gelöst werden.
+ kostenlos.
+ Gute Darstellung der Dateihistorie und
Versionsvergleiche.
o Wird bei größeren oder vielen Projekten träge.
o Benötigt etwas Einarbeitungszeit.
Framework zur Erstellung modularer Applikationen
auf Basis diverser Xaml UI Technologien. Eignet sich
besonders für komplexe Großanwendungen.
+ Bootstrapping der Anwendung.
+ Regionhandling & Navigation.
+ ViewModel Locator.
+ Integration von DI Frameworks.
+ Modulehandling / Plugins.
+ Infrastruktur für Behaviours.
+ DelegateCommands.
+ Messagebus aka EventAggregator.
+ Verschiedene Basisklassen für ViewModels.
o Bei Kleinstanwendungen eher schwergewichtig.
IoC Container der sehr gut in Kombination mit Prism
zusammen arbeitet.
+ Es gibt nur einen Typen bei dem Typen registriert
und aufgelöst werden.
+ Diverse Möglichkeiten um Einfluss auf die Lebenszeit von
Instanzen zu nehmen.
+ XML Konfiguration möglich.
+ Automatische Registrierung bestimmter Typen
einer Assembly möglich.
+ Einsatz aspektorientierter Programmierung
möglich.
o Es gibt weitaus schnellere IoC Container.
o AOP wird zur Laufzeit vorgenommen und ist
dadurch vergleichsweise langsam.
- Wird aktuell nicht sehr aktiv gepflegt.
Umfangreicher IoC Container der sehr gut mit
anderen Frameworks kombiniert werden kann.
+ Vergleichsweise schnelle Auflösung von Typen.
+ Sehr umfangreiche Möglichkeiten um Einfluss auf
die Lebenszeit von Instanzen zu nehmen.
+ Automatische Registrierung bestimmter Typen
einer Assembly möglich.
+ Für diverse .Net Plattformen verfügbar.
+ Konfiguration per XML und Json möglich.
+ Eigene Modulinfrastruktur.
+ Hervorragende Dokumentation und Pflege.
o Etwas aufwändig mit Prism zu verwenden.
o Registrierung und Auflösung von Typen geschieht
über unterschiedliche Klassen.
public IQueryable<Place> GetPlaces(int categoryId)
{
var places = this.dataBase.CategoryPlace
.Where(x => x.CategoryId == categoryId);
return this.dataBase.Place.Where(x => places
.Any(p => p.PlaceId == x.Id));
}
public Language GetLanguage(int languageId)
{
return this.dataBase.Language.Find(languageId);
}
Sehr umfangreicher objektrelationaler Mapper für
diverse .Net Plattformen.
+ Sehr einfach und intuitiv zu nutzen.
+ Gute Konfigurationsmöglichkeiten.
+ Sowohl für kleine als auch große Projekte geeignet.
+ Sehr aktive Community.
o Einsatz mit Nicht Microsoft Datenbanken
gelegentlich schwierig.
o Einfachheit täuscht darüber hinweg wie schnell
man Performanceschwachstellen entwickeln kann.
- Verwirrende Releasestrategie der
unterschiedlichen Versionen.
Werkzeug mit dem automatisierte Tests kontinuierlich
während der Programmierung ausgeführt werden.
+ Sehr schnelle Feedbackzyklen.
+ Volle Integration ins Visual Studio.
+ Sehr klare Darstellung der Testabdeckung und möglicher
Fehlerstellen.
+ Out-of-the-box Unterstützung für MS Test, NUnit, XUnit.net
+ Umfangreiche Konfigurationsmöglichkeiten.
o Nicht für Integrationstests geeignet.
o Funktionale UI
- Zugriffe auf das Dateisystem aus Tests heraus führen
häufig zu Fehlern.
Plugin für Visual Studio um XAML Code automatisch zu
formatieren.
+ Sehr einfach und leichtgewichtig.
+ Xaml Dateien sind besser lesbar.
o Reformatierung des Codes kann zu Problemen bei
Code-Reviews führen.
- Sehr große Dateien (>10k Zeilen) können das VS zum
Absturz bringen.
[TestFixture]
public class PersonValidationTests
{
[Test]
public void Error_text_shall_be_provided()
{
var sut = new Person();
Assert.That(sut["FirstName"], Is.Not.Null);
Assert.That(sut["LastName"], Is.Not.Null);
Assert.That(sut["BirthDate"], Is.Not.Null);
}
}
Sehr leistungsfähiges XUnit Testing Framework.
+ Gut geeignet für Unit und Integrationstests.
+ Wird von vielen gängigen Tools unterstützt.
+ Bietet die meisten Feautres der gängigen
XUnit Frameworks.
+ Ist sehr gut erweiterbar
+ Kann für alle gängigen .Net Plattformen eingesetzt
werden.
o Es wird ein Adapter benötigt um Tests in TFS und
VS ausführen zu können (per NuGet installierbar)
public class WhenPersonSelectionIsShown : Specifies<PersonSelectionViewModel>
{
public override void Given()
{
this.AvailablePersons = new List<Person>(){new Person()};
var repository = this.GetInstance<IRepository>();
A.CallTo(() => repository.GetPersons()).Returns(this.AvailablePersons);
}
public override void When()
{
this.SUT.OnShow();
}
[Test]
public void ThenAllAvailablePersonsAreShown()
{
Assert.AreEqual(this.AvailablePersons.Count(), this.SUT.Persons.Count());
}
public IEnumerable<Person> AvailablePersons { get; set; }
}
Leichtgewichtige Erweiterung von NUnit und MS Test
um Tests in BDD Stil zu verfassen.
+ Bietet Automocking.
+ Sehr umfangreich und leicht erweiterbar.
+ Erlaubt lesbarere Tests.
+ Ist gut erweiterbar
+ Leichtgewichtig.
o bietet vergleichsweise wenige Features moderner
BDD Frameworks.
Sehr einfaches und leicht verständliches Mocking
Framework welches einen umfassenden Einsatz von
Interfaces verlangt.
+ Sehr einfach nutz und erlernbar.
+ Tests mit FakeItEasy sind sehr gut lesbar.
+ Sehr aktive Community.
+ Weitreichend von anderen Frameworks unterstützt.
+ Sehr gute Dokumentation.
- Kann keine konkreten Typen mocken.
- Kann keine statischen Typen mocken.
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
public class HelloFiller
{
public void FillPerson()
{
var pFiller = new Filler<Person>();
pFiller.Setup()
.OnProperty(p => p.Name).Use("John")
.OnProperty(p => p.LastName).Use(new
RealNames(NameStyle.LastName));
var filledPerson = pFiller.Create();
}
}
Framework zur automatisierten Generierung von Daten.
+ Sehr einfach verständlich.
+ Sehr umfangreich.
+ Bietet Implementierungen für viele Standardfälle.
+ Gute Plugin-Infrastruktur um selbst Erweiterungen
vorzunehmen.
+ Gute Dokumentation
+ Aktive Community
o Aufwändige Konfiguration führen zu repetitivem Code.
- Keine direkte Integration in Testingframeworks.
Bietet verschiedenste Möglichkeiten um Quellcode zu analysieren, refaktorisieren und zu verbessern.

TDD für Testmuffel