TDD – Abstraktion von Testfällen

Status
Nicht offen für weitere Antworten.

Schumi

Bekanntes Mitglied
Liebe Test-getriebene Entwickler, nach einem zugegebenermaßen sehr rudimentären Einlesen in die vorgehensweise des TDD stellt sich mir eine Frage, die ich anhand einer einfachen statischen add(int, int) Methode erläutern will. Angenommen ich plane diese Methode, welche zwei ints addieren soll zu implementieren, dafür würde ich mir sukzessive Tests für interessante Fälle aufbauen:
Java:
@Test
public void testAddZeroZero()
{
  assertEquals(Adder.add(0,0),0);
}

@Test
public void testAddZeroOne()
{
  assertEquals(Adder.add(0,1),1);
}

@Test
public void testAddOneTwo()
{
  assertEquals(Adder.add(1,2),3);
}
Eine (angenommen ebenso sukzessiv entstandene) Methode die diese Tests erfüllen kann wäre zum Beispiel
Java:
public static int add(int x, int y)
{
  if(x == 1 && y == 2) return 3;
  else if(y == 1) return 1;
  else return 0;
}
Da dies wohl wenig zielführend ist, will ich in der Implementierung der Methode gerne abstrahieren. Nach meinem Verständnis des TDD-Prinzips müsste ich mir vorher aber einen entsprechenden Test formulieren:
Java:
@Test
public void testAdd()
{
  int x = n; //n sollte allgemein sein
  int y = m; //m sollte allgemein sein
  assertEquals(Adder.add(x,y), x+y)
}
Hier tut sich nun meine Frage auf, wie schaffe ich es einen solchen allgemeinen Test zu beschreiben und vor allem, wie schaffe ich es dies zu tun ohne im Test schon die Implementierung der zu testenden Methode vorweg zu nehmen (was ich in diesem Bspl. Ja durch das x+y tue)?
Ich weiß, das Beispiel ist nicht besonders glücklich gewählt, aber ich hoffe, es hilft mein Problem zu verdeutlichen.

ETA: Um es noch ein wenig anders zu formulieren: Die Frage ist, ist es möglich bzw. besser überhaupt vorgesehen von der Formulierung explizieter Beispieltestfälle auf eine allgemeine Testdefinition zu wechseln. Oder muss ich es schaffen, passende explizite Fälle (dann wohl meist Grenzfälle) zu beschreiben?
 
Zuletzt bearbeitet:

Nader

Mitglied
generell bezieht sich ein Test auf einen bestimmten Fall. Man kann in deinem Beispiel zwei unterschiedliche Aspekte erkennen: entweder will man den Fall Addition testen oder den expliziten Fall "das Addieren x+y". Beides sind nach TDD-Prinzipien durchaus sinnvoll und auch möglich zu realisieren.
 

schalentier

Gesperrter Benutzer
Mit JUnit 4 gibts die parameterisierten Tests:

Java:
@RunWith(Parameterized.class)
public class AdderTest {
   @Parameters
   public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {{1,1,0}, {1,0,1}, {2,1,1}, ... });
   }

   private int expected;
   private int a;
   private int b;

   public AdderTest( int expected, int a, int b ) {
      this.expected = expected;
      this.a = a;
      this.b = b;
   }

   @Test
   public void testAdd() {
      int actual = Adder.add( a, b );
      assertEquals( expected, actual ); 
   }
}

Ob du in der data() Methode schreibst:
Java:
{1,1,0}, {1,0,1}, {2,1,1}
oder
Java:
{1+0,1,0}, {0+1,0,1}, {1+1,1,1}
haengt vom konkreten Fall ab. Im zweiten Fall sieht man sofort, wie du zu den erwarteten Werten gekommen bist, allerdings kannst du dir so auch wunderbar selbst ein Bein stellen.

Es ist ja notwendig saemtliche Grenzfaelle abzutesten, das waeren im Besonderen also Integer.MAX_VALUE (MIN_VALUE). Wenn man dann schreibt:
Java:
{Integer.MAX_VALUE+Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}
haengt das Ergebnis eben davon ab, was genau Java mit dem Integer-Ueberlauf anstellt. Evtl. funktioniert dein Adder aber anders...
 
B

bygones

Gast
>Eine (angenommen ebenso sukzessiv entstandene) Methode
man sollte es auch mit TDD nicht übertrieben... obvious implementations are obvious

also ein einfaches add kann man dann auch ruhig einfach x+y schreiben


weiterhin hat TDD nix mit "Tests abstrahieren" zu tun... tests sollten die Normalfaelle bzw Grenzfaelle beachten, abre nicht jede moeglichkeit die es nur irgendwie gibt
 

Schumi

Bekanntes Mitglied
Danke für Eure Antworten, die parameterisierten Tests werde ich mir noch genauer anschauen müssen.

generell bezieht sich ein Test auf einen bestimmten Fall. Man kann in deinem Beispiel zwei unterschiedliche Aspekte erkennen: entweder will man den Fall Addition testen oder den expliziten Fall "das Addieren x+y". Beides sind nach TDD-Prinzipien durchaus sinnvoll und auch möglich zu realisieren.

Dies war genau mein Problem. Ich will den Fall Addition testen und die einzige Möglichkeit die mir bisher eingefallen ist, war dies über Beispielfälle zu tun.

Bigones hat gesagt.:
man sollte es auch mit TDD nicht übertrieben... obvious implementations are obvious
also ein einfaches add kann man dann auch ruhig einfach x+y schreiben
Das ist mir durchaus bewusst, das Beispiel sollte ja nur helfen mein Problem zu verdeutlichen.

Allerdings sehe ich immer noch nicht wie ich (dann doch) in dem konkreten Beispiel den Fall Addition testen könnte.
 
M

maki

Gast
Allerdings sehe ich immer noch nicht wie ich (dann doch) in dem konkreten Beispiel den Fall Addition testen könnte.
Ganz einfach ;)

Hier tut sich nun meine Frage auf, wie schaffe ich es einen solchen allgemeinen Test zu beschreiben und vor allem, wie schaffe ich es dies zu tun ohne im Test schon die Implementierung der zu testenden Methode vorweg zu nehmen (was ich in diesem Bspl. Ja durch das x+y tue)?
Du nimmst keine Implementierung vorweg, die add Methode könnte auch auf anderem Wege zu dem Ergebnis x+y kommen, wihtig ist aber dass du weisst was expected ist, und das ist nunmal x+y ;)

Denke du siehst das alles viel zu kompliziert...
 

Nader

Mitglied
..
Dies war genau mein Problem. Ich will den Fall Addition testen und die einzige Möglichkeit die mir bisher eingefallen ist, war dies über Beispielfälle zu tun.
..

den Fall x+y hast du ja testen können, wie testest du jetzt den Fall + ??

dafür musst du "+" abstrahieren, wie macht man das? indem man erstmal definiert was eigentlich addierbar sein kann, also:

Java:
interface Addierbar<A extends Number> {
    A add(A a);
}

und dann was die Addition ist:

Java:
interface Addition<A extends Addierbar> {
    A addiere(A a, A b);
}

jetzt kannst du die Impelmentierung von Addition natürlich auch testen.

Jeder würde sagen, das ist ja nicht anderes als x+y !! ich würde sagen doch, weil es sich nicht auf ein bestimmten x oder y bezieht, sondern auf die Funktion der Methode "addiere" (und auf deren Ergebnis).;)
 
Zuletzt bearbeitet:
B

bygones

Gast
Jeder würde sagen, das ist ja nicht anderes als x+y !! ich würde sagen doch, weil es sich nicht auf ein bestimmten x oder y bezieht, sondern auf die Funktion der Methode "addiere" (und auf deren Ergebnis).;)
man sollte UNBEDINGT vermeiden komplexitaet in sein Programm reinzubringen die man gar nicht braucht.

Der TO geht von [c]add(int, int)[/c] aus nicht mehr. Wenn irgendwann einmal die Anforderung kommt, diese zu generalisieren kann man (UND sollte man) dass dann (!) machen.

Nicht vorgreifen, keine Designentscheidungen treffen, die irgendwann einmal vielleicht kommen koennen - das ist Gift fuers Programmieren
 

Schumi

Bekanntes Mitglied
Noch mal danke an alle Antworter. Hat mir auf jeden Fall geholfen und ich sehe meine Frage mal als beantwortet an.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
T Organisation von Junit Testfällen? Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben