Path: csiph.com!news.mixmin.net!newsreader4.netcologne.de!news.netcologne.de!.POSTED.xdsl-78-35-223-17.netcologne.de!not-for-mail From: Patrick Roemer Newsgroups: de.comp.lang.java Subject: Re: JUnit Test von JButton: Action wird nicht erkannt Date: Thu, 14 Jul 2016 19:47:54 +0200 Organization: news.netcologne.de Distribution: world Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Date: Thu, 14 Jul 2016 17:47:55 +0000 (UTC) Injection-Info: newsreader4.netcologne.de; posting-host="xdsl-78-35-223-17.netcologne.de:78.35.223.17"; logging-data="27948"; mail-complaints-to="abuse@netcologne.de" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.24) Gecko/20100411 Thunderbird/2.0.0.24 Mnenhy/0.7.6.0 In-Reply-To: Xref: csiph.com de.comp.lang.java:12989 Responding to Christian H. Kuhn: > Vollständiger Code auf https://www.qno.de/gitweb/, Branch v0.8.4. Vielleicht bin ich nur zu doof, aber ich sehe in diesem Interface keinen Weg, das ganze Projekt einfach auszuchecken. Falls es das nicht gibt, wäre ein Link auf ein Zip oder, noch besser, ein clone des Repos auf github o.ä., sinnvoller. Was auf den ersten Blick auffällt: "Echtzeit" (System.nanoTime(), java.util.Timer, etc.) in den Kernklassen hart zu verdrahten, ist schon wegen der Tests nicht so der Knüller - die brauchen ja jetzt schon ewig... Ich würde das in irgendeine TimeSource-Abstraktion auslagern, die man in den Tests mit gescripteten Zeitwerten/-events mocken kann. Das mag die Sache durchaus etwas komplexer machen, ist aber IMHO "essential complexity" - Zeit ist nun mal nicht einfach. :) Ich würde erwarten, dass eine solche Umstellung das Design - unabhängig von den Tests - letztendlich verbessert, weil die Abhängigkeiten vom Zeitverlauf dadurch klarer ersichtlich werden sollten und man Threading (s.u.) besser wegkapseln kann. > public class QChessClockJavaAV extends JFrame implements > QChessClockObserver, ActionListener { Statt die komplette Eventlogik in einem einzigen ActionListener zu dispatchen, würde ich jedem Widget (bzw. deren Models) einen eigenen (ggfs. anonymen) ActionListener spendieren, bevorzugt in Form einer javax.swing.Action. > resetButton.doClick() löst keine Aktion aus, oder zumindest wird sie > nicht von actionPerformed() in QChessClockJavaAV aufgefangen. Dass das an resetButton.isEnabled() == false liegt, hast Du ja schon selber herausgefunden. Sowas ist übrigens genau die Art von Logik, die man in einer State Machine in einem Presentation Model kapseln und unabhängig vom UI-Framework testen kann. :) Die Widgets (bzw. deren Models) würden dann einfach mit den Events aus dem PM verdrahtet. Ansonsten hast Du auf jeden Fall noch ein Threading-Problem. Sowohl der Test (main-Thread) als auch das Kernmodell (Timer-Threads) werkeln direkt auf dem UI-Zustand rum. Das muss alles über den Swing-EDT laufen. Das ist kein rein akademisches Problem! Wenn ich im Debugger etwas mit Breakpoints und Timings rumkaspere, schaffe ich es z.B., diesen Testfall (natürlich nichtdeterministisch und nur selten) grün laufen zu lassen - weil das Deaktivieren des Reset-Buttons noch nicht im EDT "angekommen" ist und auch die stop-Action "untergeht". Das sieht dann etwa so aus: new state: NOT_STARTED thread: main from: QChessClock.addObserver(QChessClock.java:196) new state: NOT_STARTED thread: Timer-2 from: QChessClock$1.run(QChessClock.java:48) new state: RUNNING thread: main from: QChessClock.leftPressed(QChessClock.java:78) new state: NOT_STARTED thread: main from: QChessClock.resetPressed(QChessClock.java:136) Viele Grüße, Patrick