AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

DUnit - Vorgehensweise

Ein Thema von Klaus01 · begonnen am 6. Mär 2015 · letzter Beitrag vom 7. Mär 2015
Antwort Antwort
Klaus01
Online

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#1

DUnit - Vorgehensweise

  Alt 6. Mär 2015, 09:05
Hallo,

ich habe folgenden Testcase:

Delphi-Quellcode:
  TestTInBuffer = class(TTestCase)
  strict private
    FInBuffer: TInBuffer;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestIsEmpty;
    procedure TestAddBuffer;
    procedure TestGetBuffer;
    procedure TestBufferUpperLimit;
    procedure TestBufferLowerLimit;
  end;
Im Testschritt TestAddBuffer füge ich dem fInBuffer einen Buffer hinzu.
Delphi-Quellcode:
procedure TestTInBuffer.TestAddBuffer;
var
  buffer: TBuffer;
begin
  buffer := TBuffer.Create;
  fInBuffer.add(buffer);
  checkEquals(false,fInBuffer.isEmpty);
end;
Im Testschritt TestGetBuffer will ich den Buffer wieder auslesen.
Delphi-Quellcode:
procedure TestTInBuffer.TestGetBuffer;
var
  buffer: TBuffer;
begin
  buffer := fInBuffer.get;
  checkEquals(true, assigned(buffer));
  buffer.Free;
end;
Wenn fInBuffer keinen Buffer enthält - gibt fInBuffer nil als Ergenis zurück.

Der Testschritt schlägt fehl.

Ändere ich den Testschritt so ab:
Delphi-Quellcode:
procedure TestTInBuffer.TestGetBuffer;
var
  buffer: TBuffer;
  buffer1: TBuffer;
begin
  buffer1 := TBuffer.create;
  fInBuffer.add(buffer1);
  buffer := fInBuffer.get;
  checkEquals(true, assigned(buffer));
  buffer.Free;
end;
Dann schägt der Testschritt nicht mehr fehl.

Frage: Warum ist das so? Bleiben Änderungen der Test-Klasse (hier fInBuffer) zwischen den einzelnen Testschritten nicht erhalten?

Grüße
Klaus
Klaus

Geändert von Klaus01 ( 6. Mär 2015 um 09:30 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: DUnit - Vorgehensweise

  Alt 6. Mär 2015, 09:31
Für jeden Testschritt wird eine neue TestCase-Instanz erstellt.

Und das ist auch gut so, denn was du niemals machen solltest, einen Test-Schritt von einem anderen Test-Schritt abhängig machen.

Wenn dem so sein sollte, dann musst du das auch so schreiben
Delphi-Quellcode:
procedure TestTInBuffer.TestGetBuffer;
var
  buffer: TBuffer;
begin

  TestAddBuffer;

  buffer := fInBuffer.get;
  checkEquals(true, assigned(buffer));
  buffer.Free;
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Klaus01
Online

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: DUnit - Vorgehensweise

  Alt 6. Mär 2015, 09:34
.. danke - das Wissen hat mir gefehlt.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#4

AW: DUnit - Vorgehensweise

  Alt 6. Mär 2015, 23:18
Ich weiß, dass es sich in der Praxis kaum vermeiden lässt, die Funktionalität einer Methode mit dem Aufruf einer anderen abzuprüfen.
Dennoch sollte man die Interaktion in einem Unittest auf ein Mindestmaß reduzieren.

Im schlimmsten Fall haste nämlich sonst Bugs in 2 Methoden die sich gegenseitig aufheben und deine Tests sind prima grün, aber nix funktioniert.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
673 Beiträge
 
#5

AW: DUnit - Vorgehensweise

  Alt 7. Mär 2015, 00:04
Dass man eine Methode mit der anderen testet, ist manchmal sogar notwendig und gewollt. Man muß nur sicher stellen, dass die testende Methode auch getestet ist.
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#6

AW: DUnit - Vorgehensweise

  Alt 7. Mär 2015, 11:46
Die Reihenfolge der Testausführung darf keine Rolle spielen. Wenn du die Add- und Remove-Funktionalität testen willst, dann würde ich den Code duplizieren (in diesem sehr einfachen Fall). Das verstößt zwar gegen DRY, aber im Sinne der Schritte im Test (Arrange-Act-Assert) haben die Arrangements in den beiden Tests nichts miteinander zu tun.

Der Test 'TestGetBuffer' hat sein eigenes 'Arrange'. Zufällig ist das heute identisch mit dem Arrange des 'TestAddBuffer', abe morgen willst du deinen 'TestAddBuffer' vielleicht anders gestalten.

Was ich mir vorstellen kann, sind kleine Arrangement-Methoden, damit der Arrange-Code nicht zu offt dupliziert wird, so etwa:

Delphi-Quellcode:
Function TestTInBuffer.AddSampleToBuffer : TBuffer;
begin
  result := TBuffer.Create;
  fInBuffer.add(result);
end;

procedure TestTInBuffer.TestAddBuffer;
begin
   AddSampleToBuffer;
   checkEquals(false,fInBuffer.isEmpty);
end;

procedure TestTInBuffer.TestGetBuffer;
var
   buffer: TBuffer;

begin
   AddSampleToBuffer;
   buffer := fInBuffer.get;
   checkEquals(true, assigned(buffer));
   buffer.Free;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: DUnit - Vorgehensweise

  Alt 7. Mär 2015, 12:07
Man sollte sich auch von der Vorstellung lösen, dass es pro Klasse auch genau nur einen TestCase geben muss/darf.

Wenn alle Test-Methode den gleichen Ausgangs-Zustand haben müssen, dann wird dieser in der Methode SetUp festgelegt. Gibt es jetzt Test-Methoden, die damit nichts anfangen können, dann ist das wohl ein anderer Fall, also gibt es einen neuen TestCase.

Ein TestCase ist (oh Wunder) eine Klasse, mit allem was dazugehört. Die kann man auch ableiten.

Da baut man sich z.B. eine Liste mit Test-Methoden auf und leitet von dieser Klasse ein paar weitere ab, weil man dort per SetUp einfach die gleichen Prüfungen auf andere Ausgang-Zustände loslassen möchte. Das könnte ja der Fall sein, wenn ich mehrere Interface-Implementierungen testen möchte. Die Tests sind die gleichen nur die konkreten Implementierungen eben nicht.
Delphi-Quellcode:
TTestIFoo = class( TTestCase )
private
  Foo : IFoo;
published
  procedure TestFoosBar; // testet das Interface
end;

TTestIFoo_TSimpleFoo = class( TTestIFoo )
protected
  procedure SetUp;
end;

procedure TTestIFoo_TSimpleFoo.SetUp;
begin
  Foo := TSimpleFoo.Create(); // erzeugt das Interface
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz