JUnit Datapoints für mehrere Testklassen

innoc

Aktives Mitglied
Hallo zusammen,

bei der Programmierung von JUnit-Testklassen mittels Theories für die Methoden java.util.Math.sqrt() und java.util.Math.abs() auf der gleichen Menge an DataPoints ist mir folgendes Problem in den Sinn gekommen, für das ich bisher keine Lösung finden konnte. Ist es in JUnit möglich, die DataPoints für mehrere Klassen nur einmal zu definieren? Hat da jemand eine Idee, wie man das hinbekommen könnte? Der Schreibaufwand ist zwar nicht besonders groß, in jeder Testklasse das gleiche Set an DataPoints zu definieren, aber trotzdem stört es mich wegen der eigentlich unnötigen Redundanz.
Zur besseren Anschauung, nachfolgend die einzelnen Klassen:

Zuerst die TestSuite zum Aufruf der Tester-Klassen:

Java:
import junit.framework.JUnit4TestAdapter;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
  // list of comma-separated classes
  SqrtTest.class, AbsTest.class
})

public class TheoriesTestSuite {

  public static void main(String args[]) {
    junit.textui.TestRunner.run(suite());
  }

  public static junit.framework.Test suite() {
    return new JUnit4TestAdapter(TheoriesTestSuite.class);
  }
}


Als Nächstes der Math.sqrt()-Tester:

Java:
import static org.junit.Assume.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.is;

import org.junit.runner.RunWith;

import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theory;
import org.junit.experimental.theories.Theories;


@RunWith(Theories.class)
public class SqrtTest {
  // zu testende Klasse
  public static class Sqrt {
    public static Double getSqrt(Double value) {
      if (value > 0) {
        return Math.sqrt(value);
      } else {
        throw new IllegalArgumentException();
      }
    }
  }

  @DataPoints public static final Double[] VALUES = { 1D, 2D, -4D, 0D, Double.MIN_VALUE, Double.MAX_VALUE };


  @Theory public void testSqrtVerifyResult(Double value) {
    assumeThat(value > 0 && value < Double.MAX_VALUE, is(true));
    assertEquals(Math.sqrt(value), Sqrt.getSqrt(value), 0);
  }

  @Theory public void testSqrtForNegativeValues(Double value) {
    try {
      assumeThat(value < 0, is(true));
      Double result = Sqrt.getSqrt(value);
      fail("ERROR: Should throw exception");
    } catch(IllegalArgumentException ex) {
      // not required
    }
  }

  @Theory public void testSqrtForResolution(Double value) {
    Double eps = 0.000001;
    assumeThat(value > 0 && value < Double.MAX_VALUE, is(true));
    Double res = Sqrt.getSqrt(value);
    Double delta = Math.abs(value - res * res);
    assertTrue(delta < eps);
  }
    

}


Zum Schluss noch der Math.abs()-Tester:

Java:
import static org.junit.Assume.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.is;

import org.junit.runner.RunWith;

import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theory;
import org.junit.experimental.theories.Theories;


@RunWith(Theories.class)
public class AbsTest {
  // zu testende Klasse
  public static class Abs {
    public static Double getAbs(Double value) {
      return Math.abs(value);
    }
  }

  @DataPoints public static final Double[] VALUES = { 1D, 2D, -4D, 0D, Double.MIN_VALUE, Double.MAX_VALUE };

  @Theory public void testAbsVerifyResult(Double value) {
    assumeThat(value >= Double.MIN_VALUE && value <= Double.MAX_VALUE, is(true));
    assertEquals(Math.abs(value), Abs.getAbs(value), 0);
  }

  @Theory public void testAbsForNegativeResults(Double value) {
    assumeThat(value >= Double.MIN_VALUE && value < Double.MAX_VALUE, is(true));
    Double result = Abs.getAbs(value);
    assertThat(result >= 0, is(true));
  }

}

Die JUnit-Tests laufen ohne Exception durch. Mich stört nur die DataPoints sowohl in der SqrtTest-, als auch in der AbsTest-Klasse definieren zu müssen. Kann man da nicht die DataPoints aus den Testklassen auslagern, vielleicht in eine separate Klasse?
 
Zuletzt bearbeitet:
Erster Schritt wäre die Variable zwar in jedem Test zu setzen, allerdings auf eine in einer anderen Klasse definierten Konstante.
 
Abstrakte Oberklasse würde ich mal so in den Raum schmeissen.

Wenn du das nicht willst tuts auch ein "Config-Interface" mit static final Variablen.
 
Vielen Dank für die Antworten. Ich versuche es zuerst mit einer Klasse, welche die Werte in einer Enumeration enthält und welche über eine Methode getValues() abgefragt werden können.
 
OK, ich habe nun eine Lösung für das Problem. Ich habe die @DataPoints wie folgt in den Testklassen umgeschrieben:
Java:
@DataPoints public static final Double[] VALUES = new DoubleValueGenerator().getDoubleValues();

und die DoubleValueGenerator-Klasse wie folgt implementiert:
Java:
public class DoubleValueGenerator {

  Double[] getDoubleValues() {
    return new Double[] {1D, 2D, -4D, 0D, Double.MIN_VALUE, Double.MAX_VALUE };
  }

}

So hat es dann auch geklappt.
 

Zurück
Oben