Praktische Übung 'JUnit-Test' Starten Sie für die folgende Übung Eclipse und laden Sie das Testprojekt von folgender URL: http://pi.informatik.uni-siegen.de/berlik/swt/currency.zip Darin ist die Klasse Money implementiert, die Beträge einer bestimmten Währung addieren kann. Importieren Sie nun das Testprojekt (im Package Explorer rechte Maustaste / 'Import...' / 'General' / 'Existing Projects into Workspace' / 'Next >'. Unter 'Select archive file' per 'Browse...' das gespeicherte Testprojekt wählen, 'Finish'). Aufgabe 1: Schreiben Sie Tests für die Klasse Money. Am einfachsten erstellen Sie den Unit-Test über das Kontextmenü der Klasse Money.java: 'New >' / 'JUnit Test Case' / 'Finish'. Im folgenden Dialog dann das Hinzufügen von JUnit 4 zum build path per 'OK' bestätigen. Sie können den bereits erstellen Dummy-Test @Test public void test() { fail("not yet implemented"); nutzen und zu 'testadd' modifizieren. Vermutlich wird Ihr geschriebener Test fehlschlagen. Warum? Schreiben Sie dann erst die benötigten Tests für die equals Methode und danach die Methode selbst. Wenn alle Tests durchlaufen refaktorisieren Sie die Testfälle, indem Sie die Fixtures in setup auslagern. Experimentieren Sie ein wenig mit asserts, fail tests,...
Nachdem die Arbeit mit einer einfachen Währung also funktioniert, können wir anfangen Fälle mit mehreren Währungen zu bearbeiten. Das Problem ist aber, dass es für die Arithmetik mit gemischten Währung variable Wechselkurses gibt. Zur Vermeidung dieses Problems stellen wir ein MoneyBag bereit, der Währungsumrechnungen vermeidet. Werden zum Beispiel zu 12 Schweizer Franken 14 US-Dollar hinzugegeben, sind im Beutel beide Währungen vertreten, 12 CHF und 14 USD. Hinzufügen weiterer 10 Schweizer Franken ergibt einen Beutel mit 22 CHF und 14 USD. Der Gesamtwert eines MoneyBag kann später mit unterschiedlichen Wechselkursen und immer aktuell berechnet werden. Ein MoneyBag wird repräsentiert durch eine Liste von Währungen und bietet verschiedene Konstruktoren. Beachten Sie, dass die Konstruktoren privat sind, da MoneyBags hinter den Kulissen arbeiten, wenn Arithmetik mit Währung betrieben wird. public class MoneyBag implements IMoney { private Hashtable<String,Money> monies = new Hashtable<String,Money>(5); MoneyBag(Money m1, Money m2) { appendmoney(m1); appendmoney(m2); MoneyBag(Money bag[]) { for (Money money : bag) { appendmoney(money); private void appendmoney(money money) { Money m = (Money) monies.get(money.currency()); if (m!= null) { m = m.add(money); else { m = money; monies.put(money.currency(), m); Nach der Methode "code a little, test a little" erweiterten wir unsere Tests mit JUnit und stellen sicher, dass alles immer noch funktioniert. Aufgabe 2: Schreiben Sie Tests für die Klasse MoneyBag. Sie werden bei Ihren Tests wahrscheinlich die equals Methode nutzen wollen. Implementieren Sie diese und testen Sie sie. Mit dem MoneyBag können wir jetzt die Add-Methode in Money überarbeiten: public Money add(money m) { if (m.currency().equals(currency()) ) return new Money(amount()+m.amount(), currency()); return new MoneyBag(this, m); Wie oben definiert wird sich diese Methode nicht kompilieren lassen, da sie ein Money und nicht einen MoneyBag als Rückgabewert erwartet. Mit der Einführung des MoneyBag gibt es nun zwei Darstellungen für Gelder, die wir gerne verstecken würden. Dazu stellen wir eine Schnittstelle IMoney bereit, die beide Darstellungen realisiert und von den Klassen Money und MoneyBag implementiert wird. Hier ist die IMoney Schnittstelle:
public interface IMoney { public abstract IMoney add(imoney amoney); //... Um die unterschiedlichen Darstellungen vollständig vor dem Nutzer zu verstecken, müssen alle Kombinationen des Hinzufügens von Geldern und MoneyBags unterstützt werden. Aufgabe 3: Schreiben Sie Tests und Methoden, um die verschiedenen Varianten von add für alle Kombinationen von Money und MoneyBag verarbeiten zu können. testmixedsimpleadd - zwei unterschiedliche Währungen testbagsimpleadd - ein MoneyBag zu einem Money testsimplebagadd - ein Money zu einem MoneyBag testbagbagadd - zwei MoneyBags (Nachfolgend zum Vergleich die Referenzimplementierung der benötigten Klassen ohne die Unit- Tests.) Klasse Money class Money implements IMoney{ private int famount; private String fcurrency; public Money(int amount, String currency) { famount = amount; fcurrency = currency; public int amount() { return famount; public String currency() { return fcurrency; public IMoney add(imoney m) { return m.addmoney(this); public IMoney addmoney(money m) { if (m.fcurrency.equals(fcurrency) ) { return new Money(fAmount+m.fAmount, fcurrency); return new MoneyBag(this, m); public IMoney addmoneybag(moneybag s) { return s.addmoney(this); public boolean equals(object anobject) { if (anobject instanceof Money) {
Money amoney = (Money)anObject; return amoney.currency().equals(currency()) && amount() == amoney.amount(); return false; Klasse MoneyBag import java.util.hashset; import java.util.hashtable; import java.util.set; public class MoneyBag implements IMoney { private Hashtable<String,Money> monies = new Hashtable<String,Money>(5); MoneyBag(Money m1, Money m2) { appendmoney(m1); appendmoney(m2); MoneyBag(Money bag[]) { for (Money money : bag) { appendmoney(money); MoneyBag(Money m, MoneyBag bag) { appendmoney(m); appendbag(bag); MoneyBag(MoneyBag m1, MoneyBag m2) { appendbag(m1); appendbag(m2); public IMoney add(imoney m) { return m.addmoneybag(this); public IMoney addmoney(money m) { return new MoneyBag(m, this); public IMoney addmoneybag(moneybag s) { return new MoneyBag(s, this); private void appendmoney(money money) { Money m = monies.get(money.currency()); if (m!= null) { m = (Money)m.add(money); else { m = money; monies.put(money.currency(), m);
private void appendbag(moneybag abag) { for (Money m: monies.values()) { appendmoney(m); public boolean equals(object anobject) { if (!(anobject instanceof MoneyBag)) { return false; Set<Money> mymoneyset = new HashSet<Money>(monies.values()); MoneyBag other = (MoneyBag) anobject; Set<Money> othermoneyset = new HashSet<Money>(other.monies.values()); return mymoneyset.equals(othermoneyset); Interface IMoney public interface IMoney { public abstract IMoney add(imoney amoney); IMoney addmoney(money amoney); IMoney addmoneybag(moneybag amoneybag);