Laden...

[Review]Erste Unit-Tests

Erstellt von R3turnz vor 7 Jahren Letzter Beitrag vor 7 Jahren 5.572 Views
R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 7 Jahren
[Review]Erste Unit-Tests

Hallo,
ich habe nun angefangen mich mit Unit-Tests zu beschäftigen. Ich verwende xUnit und Autofixture. Hier sind meine ersten Tests:


//WeatherTests.cs//
        private Weather _dummyWeather = new Weather();
        [Theory,InlineData(-1),InlineData(101)]
        public void Humidity_InvalidValues_ExceptionThrown(double invalidHumidity)
        {
            Assert.Throws<ArgumentException>(() => _dummyWeather.Humidity = invalidHumidity);
        }
        [Theory,AutoData]
        public void TempUnit_TemperatureConvertation_TemperatureCalculated(double temperature, TemperatureUnit targetUnit)
        {
            var unit = _dummyWeather.TempUnit;
            _dummyWeather.Temperature = temperature;
            _dummyWeather.MaxTemperature = temperature;
            _dummyWeather.MinTemperature = temperature;
            _dummyWeather.TempUnit = targetUnit;
            Assert.Equal(_dummyWeather.Temperature, TemperatureUnitHelper.ConvertTemperature(unit, targetUnit, temperature),1);
            Assert.Equal(_dummyWeather.MaxTemperature, TemperatureUnitHelper.ConvertTemperature(unit, targetUnit, temperature), 1);
            Assert.Equal(_dummyWeather.MinTemperature, TemperatureUnitHelper.ConvertTemperature(unit, targetUnit, temperature), 1);    
        }
//TemperatureUnitHelperTest.cs//
        [Theory]
        [InlineData(-20,-4,253.15),InlineData(0,32,273.15),InlineData(20,68,293.15)]
        public void ConvertTemperature_CelsiusTemps_Calculated(double celsius, double expectedFahrenheit, double expectedKelvin)
        {
            Assert.Equal(expectedFahrenheit, TemperatureUnitHelper.ConvertTemperature(TemperatureUnit.Celsius, TemperatureUnit.Fahrenheit, celsius),2);
            Assert.Equal(expectedKelvin, TemperatureUnitHelper.ConvertTemperature(TemperatureUnit.Celsius, TemperatureUnit.Kelvin,celsius),2);
        }
        [Theory]
        [InlineData(250,-23.15, -9.67), InlineData(275, 1.85, 35.33),InlineData(300, 26.85, 80.33)]
        public void ConvertTemperature_KelvinTemps_Calculated(double kelvin, double expectedCelsius, double expectedFahrenheit)
...
        [Theory]
        [InlineData(-20, -28.89, 244.26),InlineData(0, -17.78, 255.37),InlineData(20, -6.67, 266.48)]
        public void ConvertTemperature_FahrenheitTemps_Calculated(double fahrenheit, double expectedCelsius, double expectedKelvin)

Das sind noch relativ simple Tests ohne Mocking etc. Gibt es trotzdem Verbesserungsmöglichkeiten?

16.806 Beiträge seit 2008
vor 7 Jahren

Nimm FluentAssertions, womit die Tests viel übersichtlicher werden als mit Assert.Xy

D
985 Beiträge seit 2014
vor 7 Jahren

Die _dummyWheather Instanz sollte vor dem Aufruf jeder Test-Methode neu erstellt werden, sonst hat man nachher irgendwelche SideEffects drin und der UnitTest ist für die Katz.

Die Test-Frameworks stellen dafür Attribute zur Verfügung, um Methoden zu kennzeichnen, die vor oder nach jeder Test-Methode aufgerufen werden.

Wenn du einen ungültigen Humidity-Wert setzt wirfst du dann tatsächlich nur eine ArgumentException? Ich hätte da eine ArgumentOutOfRangeException erwartet.

16.806 Beiträge seit 2008
vor 7 Jahren

Das hab ich ganz übersehen.
Allgemein sollte man nicht über verschiedene Tests irgendwelche Objekte teilen - ansonsten wäre auch der Name Unit für die Katz.

Siehe: [Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 7 Jahren

Ich verwende wie oben erwähnt xUnit und hier wird der und nicht die mit Setup markierte Methode sondern der Konstruktor vor jedem Test ausgeführt (Siehe Vergleich von Unit-Testing Frameworks)

16.806 Beiträge seit 2008
vor 7 Jahren

Trotzdem macht es relativ wenig sinn 😃 Dann evtl. sogar noch weniger.
Zudem erschwert es potentielles Mocking bei weiteren Tests...

Is nur nen Rat; und Du wolltest Feedback.
Und aus Erfahrung sag ich Dir, dass man nicht alle Features sinnvoll verwenden kann 😃
Ich verwende auch XUnit und vermeide jeglichen Constructor stuff.
Aber vielleicht gibts natürlich auch Leute, die damit positive Erfahrung gemacht haben könnten.

R
R3turnz Themenstarter:in
125 Beiträge seit 2016
vor 7 Jahren

Okay, ich habe bisher noch nicht viel mit Mocking gemacht. Werde dann einfach entscheiden ob es für mich Sinn macht. Inwiefern setzt du dann soetwas um, da es kein Setup-Attribut gibt?

P
1.090 Beiträge seit 2011
vor 7 Jahren

Hallo R3turnz,

vielleicht Grundlegen erst mal, Unit Test ohne Mocks zu schreiben ist nicht schlecht. Laut Kennt Beck (TTD) sollte man wenn man Mocks benutzten muss. Erstmal prüfen ob nicht ein Fehler im designe Vorliegt. Es gibt aber durch aus gründe sie zu Verwenden, gerade im Umgang mit Legacy Code.

Der 1. Test (Humidity_InvalidValues_ExceptionThrown ) ist grundlegend Gut. Ok Humidity musste ich jetzt erst mal mit Leo über setzen. Luftfeuchtigkeit ist halt ein Wert der in % Angegeben wird. Hier kannst du vielleicht noch bei den Test einen Kommentar mit geben (z.B. Humidity ist ein Prozentwert). So das dann andere auch wissen wie so der Test fehlgeschlagen ist. Bei Humidity ist es vielleicht noch trivial, aber wenn die Anwendung etwas Komplexer ist, sollte deinen Kollegen mitgeteilt werden wie so der Test fehlgeschlagen ist. Es kann ja sein das sich die Anforderungen ändern und das es dann Korrekt ist, das der Test fehlschlägt und angepasst werden muss.

Dann ist es noch ein Positive Test, du erwartest das ein Exception geworfen wird, also Prüfst du ob eine Exeption geworfen wird. Hier fehlt eigentlich noch der Negativ Test (wird oft Vergessen), wird bei 0 und 100 keine Exception geschmissen.

Bei den anderen Test ist mir nicht klar wie so du gerade diese Testwerte gewählt hast, für mich wirken sie jetzt recht willkürlich. Bei Doubel Werten ist meist Interessant was bei was bei den Extremen Passiert (Min/Max Double) und aus was um 0 herum Passiert (-1,0,1) (Hier ändern viele Funktionen ihr Verhalten). Grundlegend muss man schauen wo was Interessantes passiert und schauen das man da passend die Test schreibt. Bei dir ist es z.B. der Absolute Nullpunkt (0K / -273,15C). Was passiert also bei den Werten -273,16C, -273,15C ,-273,14C)

MFG
Palin

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

2.207 Beiträge seit 2011
vor 7 Jahren

Hallo R3turnz,

wundere mich, dass noch keine "Arrange - Act - Assert" in den Raum geworfen hat. Das vielleicht auch mal anschauen. Gerade was die angesprochene Eigenständigkeit von Unit-Tests angeht wäre der Fehler vielleicht gar nicht passiert.

Gruss

Coffeebean