<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3954848516178620733</id><updated>2011-04-21T20:05:25.004-07:00</updated><title type='text'>Stoyan  Vassilev</title><subtitle type='html'>Java, Clojure, coding and not much else.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://stoto79.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3954848516178620733/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://stoto79.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stoyan Vassilev</name><uri>http://www.blogger.com/profile/10811809413773235020</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://1.bp.blogspot.com/_mfOsPJLv32o/SSEnJQagV6I/AAAAAAAAAdA/vlBUwXDDhWE/S220/MeInTennessee.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3954848516178620733.post-3621742112237654220</id><published>2008-11-26T15:28:00.000-08:00</published><updated>2008-12-04T10:54:12.451-08:00</updated><title type='text'>On the Use of Template Methods</title><content type='html'>I find the &lt;a href="http://en.wikipedia.org/wiki/Template_method_pattern"&gt;template method&lt;/a&gt; design pattern too easy to get wrong, not trivial to maintain, and downright unnecessary--considering the alternatives--to be worth the trouble. The intent of the template method pattern as postulated by the gang of four is to "define the skeleton of an algorithm in an operation, deferring some steps to subclasses" [1]. In the &lt;i&gt;Applicability &lt;/i&gt;section, the authors include a couple more scenarios when the pattern "&lt;i&gt;should&lt;/i&gt;", be used: &lt;ul&gt;&lt;li&gt;&lt;p style="margin-bottom: 0in;"&gt;"when common behavior among  subclasses should be factored and localized in a common class"  [1]&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;when implementing "hook operations": methods that  get called at certain points in the execution of an algorithm that  children may override.   &lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I am yet to see a convincing case when the template method is the best solution for &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; object-oriented design problem.  Here's why:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Easy To Get Wrong and Suboptimal Even When Implemented Properly&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p style="margin-bottom: 0in;"&gt;When using template methods as  concrete steps in the skeleton of an algorithm, the parent  class--the one containing the operation skeleton--&lt;b&gt;must be  explicit in what step methods children &lt;/b&gt;&lt;i&gt;&lt;b&gt;must&lt;/b&gt;&lt;/i&gt;  &lt;b&gt;override and what methods/steps children &lt;/b&gt;&lt;i&gt;&lt;b&gt;may &lt;/b&gt;&lt;/i&gt;&lt;b&gt;override&lt;/b&gt;. A way of communicating this in Java is having must-override methods be abstract (or pure virtual in C++) while having may-override methods have an non-final implementation in the parent class. Parents' providing default implementations, however minimal or convenience no-ops, to  methods child classes must override anyway is unnecessary and  confusing to readers and clients of the code.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0in;"&gt;The concrete implementation of template methods in the  concrete class &lt;span style="font-weight: bold;"&gt;must be final&lt;/span&gt;. Otherwise, allowing further inheritance of a concrete class that provides template method implementations, creates a maintenance mess as the only way to ever extends behavior is through further inheritance.&lt;br /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Putting 1 and 2 together we get the following:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;public class FancyReportSender {&lt;br /&gt;public void doSend() {&lt;br /&gt;try {&lt;br /&gt;  // Do fancy work&lt;br /&gt;  Connection c = openConnection();&lt;br /&gt;  if (isConnectionOpen()) {&lt;br /&gt;    // Do more fancy work&lt;br /&gt;    // Send data using connection c&lt;br /&gt;  }&lt;br /&gt;} finally {&lt;br /&gt;  closeConnection();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;abstract protected Connection openConnection();&lt;br /&gt;abstract protected boolean isConnectionOpen();&lt;br /&gt;abstract protected void closeConnection();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public final class SerialCommFancyReportSender extends FancyReportSender {&lt;br /&gt;protected Connection openConnection() {&lt;br /&gt; // open and return a serial port connection&lt;br /&gt;}&lt;br /&gt;protected boolean isConnectionOpen() {&lt;br /&gt; // return if connection was open fine ...&lt;br /&gt;}&lt;br /&gt;protected void closeConnection() {&lt;br /&gt; // close it ...&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Code Listing 1: Standard template method implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some immediate problems with the approach above is that we have coupled the sender  with the serial connection piece in a IS-A relationship. Besides just the standard composition-wins-over-inheritance argument, we see that we have coupled the responsibility of doing the sending with the responsibility of opening a serial type connection in the SerialCommFancyReportSender class. As a result, should we need to open a serial connection in a context other than the FancyReportSender, our SerialCommFancyReportSender is not of much use.&lt;br /&gt;&lt;br /&gt;Furthermore, subclassing is the only way to provide these concrete connection-management steps: SerialCommFancyReportSender &lt;span style="font-style: italic;"&gt;must &lt;/span&gt;extend the FancyReportSender class--as opposed to, say, implementing an interface--and this fact further restricts the class that might provide that concrete behavior.&lt;br /&gt;&lt;br /&gt;And lastly, in practice, the line between what must and what may be overriden in a child class using template methods can get blurry over time. When common functionality exists for a given step, future developers maintaining the code might be tempted to push that commonality to the common base and expect client code to call super. Things can get sloppy very quick.&lt;br /&gt;&lt;br /&gt;Consider the following composition alternative to template methods:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;public class FancyReportSender {&lt;br /&gt;private final IConnectionProvider m_connectionProvider;&lt;br /&gt;public FancyReportSender (IConnectionProvider connectionProvider) {&lt;br /&gt; m_connectionProvider = connectionProvider;&lt;br /&gt;}&lt;br /&gt;public void doSend() {&lt;br /&gt; try {&lt;br /&gt;   Connection c = m_connectionProvider.openConnection();&lt;br /&gt;   if (m_connectionProvider.isConnectionOpen()) {&lt;br /&gt;     // do stuff with connection c&lt;br /&gt;   }&lt;br /&gt; } finally {&lt;br /&gt;   m_connectionProvider.closeConnection();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public final class SerialConnectionProvider implements IConnectionProvider {&lt;br /&gt;public Connection openConnection() {&lt;br /&gt; // open and return connection on a serial port&lt;br /&gt;}&lt;br /&gt;public boolean isConnectionOpen() {&lt;br /&gt; // return if connection was open fine ...&lt;br /&gt;}&lt;br /&gt;public void closeConnection() {&lt;br /&gt; // close it ...&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface IConnectionProvider {&lt;br /&gt;Connection openConnection();&lt;br /&gt;boolean isConnectionOpen();&lt;br /&gt;void closeConnection();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Code Listing 2: Composition Alternative&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;to Template Methods&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This composition alternative addresses the problems above and leaves greater flexibility for clients providing the concrete steps.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Not Trivial To Maintain&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;Since template methods set the tone of class extension as the way of extending class behavior, in practice one often sees the application of template methods deteriorate to something like the following:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_mfOsPJLv32o/STdxxADK-XI/AAAAAAAAA4A/P4fBtDVwDJ8/s1600-h/diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 355px; height: 400px;" src="http://4.bp.blogspot.com/_mfOsPJLv32o/STdxxADK-XI/AAAAAAAAA4A/P4fBtDVwDJ8/s400/diagram.png" alt="" id="BLOGGER_PHOTO_ID_5275810575128656242" border="0" /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;Diagram 1: Template Methods Pave the Way to Vertical Design&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As a result, the class hierarchy can get very vertical, very fast. Concrete template method implementations often end up on a various "floors" in the hierarchy, and, at coding time, inspecting a piece of code in CommConnectionFancySender, say, presents a challenge to determine on what floor a method implementation that will get called at run-time, really lives.&lt;br /&gt;&lt;br /&gt;In such a design, class attributes end up spread all over the hierarchy, and there is no protection against a future developer maintaining the code and reducing data visibility of parent data from private to protected in order to make it accessible to children.&lt;br /&gt;&lt;br /&gt;While debugging, what we see is that stepping-into a method can cause the program counter to jump up and down the hierarchy, binding to the right method: at any given instant, for a class in such a design, a method call can "land" in a parent, a child or in the class itself.&lt;br /&gt;&lt;br /&gt;For a project of a reasonable size, we end up with a maintenance gem on our hands.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Template Methods as Hook Operations&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If we recall the GOF definition of hook operations, these are operations that get called by the parent at times when they wish to give control to their children classes. Therefore, by their very nature hook operations promote temporal cohesion, as clients often end up sticking code in the hook implementation that is there mostly because of &lt;span style="font-style: italic;"&gt;when &lt;/span&gt;it needs to get called: code that ends up in concrete versions of the various Eclipse RCP advisors, such as  &lt;a href="http://publib.boulder.ibm.com/infocenter/rsdhelp/v7r0m0/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/application/WorkbenchWindowAdvisor.html"&gt;WorkbenchWindowAdvisor.preWindowRestore()&lt;/a&gt; are a good case in point. Plus, when implementing hook methods as template methods, we design in the unnatural restriction that hooking in can happen only by class extension.&lt;br /&gt;&lt;br /&gt;As an alternative to hook methods, a plain callback interface can be used: at the very least, it won't require class extending to insert an hook. But a callback interface will still keep the temporal cohesion problem.&lt;br /&gt;&lt;br /&gt;Some variation of the observer-subject pattern is probably a better fit: it will allow orthogonal operations to register separate concrete observers, and get notified separately, thereby avoiding the temporal cohesion in a single method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final Thought&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Template methods are not evil. But I, for one, have not come across a case when they were ever the best design decision.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3954848516178620733-3621742112237654220?l=stoto79.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stoto79.blogspot.com/feeds/3621742112237654220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3954848516178620733&amp;postID=3621742112237654220' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3954848516178620733/posts/default/3621742112237654220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3954848516178620733/posts/default/3621742112237654220'/><link rel='alternate' type='text/html' href='http://stoto79.blogspot.com/2008/11/on-use-of-template-methods.html' title='On the Use of Template Methods'/><author><name>Stoyan Vassilev</name><uri>http://www.blogger.com/profile/10811809413773235020</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://1.bp.blogspot.com/_mfOsPJLv32o/SSEnJQagV6I/AAAAAAAAAdA/vlBUwXDDhWE/S220/MeInTennessee.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_mfOsPJLv32o/STdxxADK-XI/AAAAAAAAA4A/P4fBtDVwDJ8/s72-c/diagram.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3954848516178620733.post-6456949221246507178</id><published>2008-11-17T00:24:00.000-08:00</published><updated>2008-11-22T12:45:04.923-08:00</updated><title type='text'>Clojure meets Behavior-Driven Development</title><content type='html'>While studying &lt;a href="http://www.clojure.org/"&gt;Clojure&lt;/a&gt; and doodling with possible usages of its smooth interop with Java, &lt;a href="http://easytesting.org/wiki/pmwiki.php"&gt;FEST&lt;/a&gt; came to mind: a clever, fluent-inteface GUI-driven functional testing framework for Swing.&lt;br /&gt;&lt;br /&gt;Clojure brings to the table a dynamic, highly expressive language that reads as a script but is compiled to Java bytecode on the fly.  FEST brings festivities and testing to the picture: it provides fluent Java interfaces for driving Swing UIs, as well as an assertions library. My curiosity was piqued at giving BDD a shot at this. Here's my notes:&lt;br /&gt;&lt;br /&gt;My proof-of-concept case tests a simple login frame: prosaic, but illustrates the idea. We are given a requirement that the "Sign in" button should be enabled only when a username and password are provided. The "Cancel" button must always be enabled. The user story  in BDDspeak and Clojure&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(ns conducta.login-sample)&lt;br /&gt;(use 'conducta.bdd)&lt;br /&gt;(use 'conducta.ui)&lt;br /&gt;&lt;br /&gt;(User-story "As a system user, I want to be able to submit my credentials, so that I can access my account.")&lt;br /&gt;&lt;br /&gt;(defn Enter-credentials-submit-enabled-scenario&lt;br /&gt;"The 'Submit' button is disabled by default. When the user types in their username and password, the 'Submit' button turns enabled."&lt;br /&gt;[username password role signin]&lt;br /&gt;&lt;br /&gt;(Given "that the sign-in button is disabled")&lt;br /&gt;(require-disabled! signin)&lt;br /&gt;&lt;br /&gt;(When "username and password are typed in")&lt;br /&gt;(enter-text "bobsmith" username)&lt;br /&gt;(enter-text "bobspassword" password)&lt;br /&gt;&lt;br /&gt;(And "user is selected")&lt;br /&gt;(select-item "User" role)&lt;br /&gt;&lt;br /&gt;(Then "sign-in button should become disabled")&lt;br /&gt;(require-enabled! signin)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(defn Login-button-disabled-on-clearing-scenario&lt;br /&gt;"Having enabled the 'Submit' button on entering username and the password, the user deletes the username. The 'Submit' button must then turn back to disabled"&lt;br /&gt;[username password signin]&lt;br /&gt;&lt;br /&gt;(require-disabled! signin)&lt;br /&gt;(enter-text "bobsmith" username)&lt;br /&gt;&lt;br /&gt;(When "password is entered and then removed")&lt;br /&gt;(enter-text "bobspassword" password)&lt;br /&gt;(delete-text password)&lt;br /&gt;&lt;br /&gt;(Then "sign-in button should turn disabled")&lt;br /&gt;(require-disabled! signin)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(defn User-cancels-login-scenario&lt;br /&gt;"'Cancel' button is enabled whether we have a username or password entered."&lt;br /&gt;[username password cancel]&lt;br /&gt;(require-enabled! cancel)&lt;br /&gt;(enter-text "bobsmith" username)&lt;br /&gt;(require-enabled! cancel)&lt;br /&gt;(delete-text username)&lt;br /&gt;(require-enabled! cancel)&lt;br /&gt;(enter-text "bobspassword" password)&lt;br /&gt;(require-enabled! cancel)&lt;br /&gt;(delete-text password)&lt;br /&gt;(require-enabled! cancel)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Code Listing 1: login-sample.clj&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Good points about this approach:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Terse, reads intuitively&lt;/li&gt;&lt;li&gt;Phrased in natural imperative sentences: non-technical staff must have no problem reading or even creating/maintaining this&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Runs as JUnit (see more below).  As such, it benefits from all ANT tools, IDE integration, and can be hooked with the continious build.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It is a Clojure script: interactive, can be tested from the Repl, plus extendability comes cheap. For example, extending it with higher level constructs using macros and functions--first class citizens in Clojure--does not require parser changes (unlike an ad-hoc DSL). To illustrate, say we need to write an integration test that does something after login. So development can create the following &lt;span style="font-style: italic;"&gt;login &lt;/span&gt; function&lt;/li&gt;&lt;pre class="prettyprint lang-lisp"&gt;(defn login&lt;br /&gt;"Authenticates a test user"&lt;br /&gt;[]&lt;br /&gt;(enter-text "user01" username)&lt;br /&gt;(enter-text "tkv123" password)&lt;br /&gt;(select-item "User" role-selector)&lt;br /&gt;(click submit)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, non-technical staff reading the scenario now sees&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&lt;br /&gt;(login)&lt;br /&gt;(select-item "My Account" navigator-bar)&lt;br /&gt;;; ... and so on.&lt;br /&gt;&lt;/pre&gt;The "log in" action got promoted to a higher-level abstraction. Duplication and verbosity were avoided with a minimum effort.&lt;br /&gt;&lt;li&gt;The script is potentially UI-toolkit- and UI-component-agnostic. Code like&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(select-item "User" role)&lt;br /&gt;&lt;/pre&gt;binds at runtime, and can execute as "select 'User' from a combo box","select a radio button, labeled 'User'" and so on. Also, &lt;span style="font-style: italic;"&gt;select-item &lt;/span&gt;could dispatch to a Swing, SWT or web bot call.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A user reading &lt;span style="font-style: italic;"&gt;Code Listing 1&lt;/span&gt; need not know a thing about JUnit or fixtures. That is managed by the JUnit portion of this solution (&lt;span style="font-style: italic;"&gt;Code Listing 2&lt;/span&gt;) which is dev-land.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;The output from running the user story in REPL:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.user=&gt; (. junit.textui.TestRunner run conducta.FESTTest)&lt;br /&gt;As a system user, I want to be able to submit my credentials, so that I can acce&lt;br /&gt;ss my account.&lt;br /&gt;.&lt;br /&gt;Starting scenario:  The 'Submit' button is disabled by default. When the user&lt;br /&gt;types in their username and password, the 'Submit' button turns enabled.&lt;br /&gt; Given  that the sign-in button is disabled&lt;br /&gt; When  username and password are typed in and  user is selected&lt;br /&gt; Then  sign-in button should become disabled&lt;br /&gt;.&lt;br /&gt;Starting scenario:  Having enabled the 'Submit' button on entering username a&lt;br /&gt;nd the password, the user deletes the username. The 'Submit' button must then tu&lt;br /&gt;rn back to disabled&lt;br /&gt; When  password is entered and then removed&lt;br /&gt; Then  sign-in button should turn disabled&lt;br /&gt;.&lt;br /&gt;Starting scenario:  'Cancel' button is enabled whether we have a username or&lt;br /&gt;password entered.&lt;br /&gt;&lt;br /&gt;Time: 15.685&lt;br /&gt;&lt;br /&gt;OK (3 tests)&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Output Listing 1: Running login-sample.clj in the REPL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The JUnit Test Case that will drive the user story is listed below. First, I stubbed a FESTTest.class with&lt;br /&gt;&lt;code class="prettyprint lang-lisp"&gt;&lt;br /&gt;user=&gt; (gen-and-save-class "." "conducta.FESTTest" :extends junit.framework.Test&lt;br /&gt;Case :methods [["testSubmitEnabledOnCredentials" [] (Void/TYPE)]["testDisabledOn&lt;br /&gt;ClearingText" [] (Void/TYPE)]["testCancelEnablement" [] (Void/TYPE)] ])&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Next, generated  FESTTest.clj that will&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create FEST FrameFixture in setUp() method, and child widgets' fixtures &lt;/li&gt;&lt;li&gt;Call individual scenarios in every test* method&lt;/li&gt;&lt;li&gt;Tear down the fixture in cleanUp()&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;code class="prettyprint lang-lisp"&gt;(ns conducta)&lt;br /&gt;(use 'conducta.ui)&lt;br /&gt;(use 'conducta.login-sample)&lt;br /&gt;(use 'conducta.bdd)&lt;br /&gt;&lt;br /&gt;(import '(org.fest.swing.fixture FrameFixture))&lt;br /&gt;(import '(com.foo MyFrame))&lt;br /&gt;&lt;br /&gt;(def frameFixture)&lt;br /&gt;(def start-scenario-prefix "   Starting scenario: ")&lt;br /&gt;&lt;br /&gt;;; set up the frame fixture&lt;br /&gt;(defn FESTTest-setUp [_]&lt;br /&gt;(def frameFixture (FrameFixture. (MyFrame.)))&lt;br /&gt;(.show frameFixture)&lt;br /&gt;(def username (widget (text frameFixture "username")))&lt;br /&gt;(def role (widget (combo frameFixture "selector")))&lt;br /&gt;(def password (widget (text frameFixture "password")))&lt;br /&gt;(def signin (widget (button frameFixture "signInButton")))&lt;br /&gt;(def cancel (widget (button frameFixture "cancelButton")))&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;;;  Actual tests&lt;br /&gt;(defn FESTTest-testSubmitEnabledOnCredentials [_]&lt;br /&gt;;; TODO: Change to using a lazy seq and evaluate&lt;br /&gt;(println)&lt;br /&gt;(println start-scenario-prefix&lt;br /&gt;(get ^#'Enter-credentials-submit-enabled-scenario :doc))&lt;br /&gt;(Enter-credentials-submit-enabled-scenario username password role signin)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;(defn FESTTest-testDisabledOnClearingText [_]&lt;br /&gt;(println)&lt;br /&gt;(println start-scenario-prefix&lt;br /&gt;(get ^#'Login-button-disabled-on-clearing-scenario :doc))&lt;br /&gt;(Login-button-disabled-on-clearing-scenario&lt;br /&gt;username password signin)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(defn FESTTest-testCancelEnablement [_]&lt;br /&gt;(println)&lt;br /&gt;(println start-scenario-prefix (get ^#'User-cancels-login-scenario :doc))&lt;br /&gt;(User-cancels-login-scenario username password cancel)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;;; Other GUI tests ... Test domain-agnostic GUI things: tab traversal order,&lt;br /&gt;;; resizing, etc.&lt;br /&gt;&lt;br /&gt;;; clean-up code&lt;br /&gt;(defn FESTTest-tearDown [_] (.cleanUp frameFixture))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Code Listing 2: The JUnit test case implemented in Clojure and driving the GUI using FEST&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Finally, the code that dispatches Clojure to FEST APIs or potentially other UI driving frameworks, like SWTBot.&lt;br /&gt;&lt;br /&gt;&lt;code class="prettyprint lang-lisp"&gt;(ns conducta.ui)&lt;br /&gt;(import '(org.fest.swing.fixture FrameFixture))&lt;br /&gt;&lt;br /&gt;(defmulti widget :Component)&lt;br /&gt;(defn combo [window name] {:Component :combo :window window :name name})&lt;br /&gt;(defn text [window name] {:Component :text :window window :name name})&lt;br /&gt;(defn button [window name] {:Component :button :window window :name name})&lt;br /&gt;&lt;br /&gt;;; TODO pull code below in a separate fest-swing.clj&lt;br /&gt;(defmethod widget :combo [c] (. (:window c) comboBox (:name c)))&lt;br /&gt;(defmethod widget :text [t] (. (:window t) textBox (:name t)))&lt;br /&gt;(defmethod widget :button [b] (. (:window b) button (:name b)))&lt;br /&gt;&lt;br /&gt;;; Text related&lt;br /&gt;(defn enter-text [text widget] (.enterText widget text))&lt;br /&gt;(defn delete-text [widget] (.deleteText widget))&lt;br /&gt;(defn select-item [item widget] (.selectItem widget item))&lt;br /&gt;&lt;br /&gt;;; General&lt;br /&gt;(defn click [widget] (.click widget))&lt;br /&gt;(defn focus [widget] (.focus widget))&lt;br /&gt;&lt;br /&gt;;; require*&lt;br /&gt;(defn require-enabled! [widget] (.requireEnabled widget))&lt;br /&gt;(defn require-disabled! [widget] (.requireDisabled widget))&lt;/code&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Code Listing 3: ui.clj the code that bridges to FEST&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Project &lt;a href="http://code.google.com/p/conducta/"&gt;Conducta&lt;/a&gt; is in prototype stages. I have not added the code to source control yet, but will do so over the weekend. It is set up with Apache2.0 license.&lt;br /&gt;&lt;br /&gt;Feedback, ideas on idiomatic Clojure are always welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3954848516178620733-6456949221246507178?l=stoto79.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://stoto79.blogspot.com/feeds/6456949221246507178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3954848516178620733&amp;postID=6456949221246507178' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3954848516178620733/posts/default/6456949221246507178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3954848516178620733/posts/default/6456949221246507178'/><link rel='alternate' type='text/html' href='http://stoto79.blogspot.com/2008/11/clojure-meets-bdd.html' title='Clojure meets Behavior-Driven Development'/><author><name>Stoyan Vassilev</name><uri>http://www.blogger.com/profile/10811809413773235020</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='http://1.bp.blogspot.com/_mfOsPJLv32o/SSEnJQagV6I/AAAAAAAAAdA/vlBUwXDDhWE/S220/MeInTennessee.jpg'/></author><thr:total>3</thr:total></entry></feed>
