Java - JUnit Test Failue trotz korrektem Ergebnis?

KAEPS133

Freizeitschrauber(in)
Hallo,

Ich habe grade eine Lösung einer Programmieraufgabe geschickt bekommen bei der es um Bruche geht. Die Klasse Bruch ist soweit korrekt implementiert mit allen Grundrechenarten, toDouble, toString und equals. Das funktioniert auch alles wunderbar wenn man es über eine Main startet und dort neue Bruchobjekte erzeugt und mit diesen rechnet.

Der JUnit-Test sieht so aus:

Code:
public class JTest {

	@Test
	public void testShouldCompareEqualFractions() {
	Bruch a = new Bruch(2,3);
	Bruch b = new Bruch(4,6);
	assertEquals(a,b);
	}
	
	@Test
	public void testShouldAddFractions() {
	Bruch a = new Bruch(3,4);
	Bruch b = new Bruch(1,4);
	assertEquals(Bruch.add(a,b), a.add(b));
	assertEquals(1.0, a.toDouble(), 0);
	}
}

Dieser Schlägt aber mit 2 Failures fehl:
java.lang.AssertionError: expected: oop.Bruch<(2/3)> but was: oop.Bruch<(2/3)>
java.lang.AssertionError: expected: oop.Bruch<(1/1)> but was: oop.Bruch<(1/1)>

Wo genau ist da jetzt der Fehler ?!
 
Wie sieht denn die equals Methode aus? Eventuell ist das ja ein Problem mit der Genauigkeit (Floats auf Gleichheit ohne Delta zu testen ist riskant).
 
Er hat die Beiden Brüche als Double ausgerechnet und verglichen, wobei er eigentlich auch einfach jeweils Nenner und Nenner sowie die Zähler hätte vergleichen können da jeder neue Bruch direkt gekürzt wird.

Code:
	public boolean equals(Bruch other) 
	{
		double a = (double)this.zaehler / (double)this.nenner;
		double b = (double)other.getZaehler() / (double)other.getNenner();
		
		if(a == b) return true;
		else return false;
	}
 
Die Signatur der Equals-Methode in der Klasse Object ist
Code:
public boolean equals([b]Object[/b])
und nicht
Code:
public boolean equals([b]Bruch[/b])
Folglich wird die Methode auch nicht durch die Equals-Methode in der Klasse Bruch überschrieben.

Abgesehen davon scheint der Code auch ziemliche Grütze zu sein.
 
Zuletzt bearbeitet:
Genau, das equals wurde überladen und nicht überschrieben (@override ist bei so etwas übrigens sehr hilfreich). Und die beiden doubles mit == vergleichen kann wie gesagt auch zu Problemen führen.

Eine Möglichkeit wäre so etwas hier (EPS = gewünschte Genauigkeit):
Code:
return Math.abs(a - b) < EPS;
 
Ist das eigentlich wirklich so beabsichtigt, dass die Klasse Bruch mutable ist und es eine statische Add-Methode gibt? Mir ist schon klar, dass der Code von jemandem stammt, der gerade erst beginnt Java bzw. Programmieren zu lernen. Mich würde nur interessieren, ob das ganze auf Unwissenheit/-erfahrenheit beruht oder ob das tatsächlich so durch die Aufgabenstellung vorgegeben war.
 
Ja das ist wohl so in der Aufgabenstellung Vorgegeben.

Code:
public static Bruch add(Bruch a, Bruch b);
public static Bruch sub(Bruch a, Bruch b);
public static Bruch mul(Bruch a, Bruch b);
public static Bruch div(Bruch a, Bruch b);
public Bruch add(Bruch other);
public Bruch sub(Bruch other);
public Bruch mul(Bruch other);
public Bruch div(Bruch other);
 
Dadurch wird aber nicht vorgegeben, dass Bruch mutable sein soll. Ich bezweifle auch ernsthaft, dass das so gewollt ist.
add, sub, usw. sollten ein neues Bruch-Objekt zurückgeben und nicht das vorhandene verändern und dann zurückgeben.

Edit: Noch kurz ein paar Gründe, warum es ungünstig ist die Klasse mutable zu machen:
  • Das aktuelle Verhalten von Bruch ist unüblich und somit unerwartet.
  • Es entstehen leicht ungewollte Nebeneffekte.
  • Es ist sematisch ziemlicher Käse.
 
Zuletzt bearbeitet:
Überlegen Sie: Was ist ein Bruch, wie lässt er sich in einem Programm darstellen und implementieren? Erstellen
Sie eine eine Klasse, die einen Bruch implementiert und dazu die vier Grundrechenarten
• Addition
• Subtraktion
• Multiplikation
• Division
für ein Objekt dieser Klasse bereitstellt.

Mehr steht da nicht, also ist für die Aufgabenstellung egal ob mutable oder immutable. Die beiden fields private int zaehler; private int nenner; werden auch nur von der Funktion kuerzen verändert. Ich sehe da für die Aufgabenstellung auch kein großes Problem.
 
Die beiden fields private int zaehler; private int nenner; werden auch nur von der Funktion kuerzen verändert.

Sicher? Kann ich die Add-Methode mal sehen?

Im Hinblick auf den Code aus dem Unit-Test würde ich nämlich stark davon ausgehen, dass hier das Bruch-Objekt verändert wird.
Code:
Bruch a = new Bruch(3,4);
Bruch b = new Bruch(1,4);
assertEquals(Bruch.add(a,b), a.add(b));
assertEquals(1.0, a.toDouble(), 0);

Oder soll das letzte assertEquals fehlschlagen?
 
Zuletzt bearbeitet:
Achsooo deswegen kommst du darauf. Ja das hab ich vergessen zu sagen :ugly:
assertEquals(1.0, a.toDouble(), 0); war ein Fehler im Aufgabenblatt. Da wird vorher ein neuer Bruch c erstellt bei dem a und b addiert werden.
Und ich hab mich die ganze zeit gefragt wie du darauf kommst:daumen:

Code:
public static Bruch add(Bruch a, Bruch b) {
		int aZaehler = a.getZaehler();
		int aNenner = a.getNenner();
		
		int bZaehler = b.getZaehler();
		int bNenner = b.getNenner();
		
		int newZaehler = aZaehler * bNenner + bZaehler * aNenner;
		int newNenner  = aNenner * bNenner;
				
		return new Bruch(newZaehler, newNenner);
	}
 
Zurück