Really Cool TDD in D6

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Really Cool TDD in D6

TimM-3
There are a lot of possibilities to do really effective TDD in smalltalk -
especially D6, in fact I'm really enjoying it. Someone on here pointed me in
the right direction - adding an accelerator "Ctrl-0" to run your tests. Even
better is to build on that tip and add another one to the SUnit browser to
get you back.

The feeling then becomes a lot like Eclipse and IntelliJ (how I've been
selling D6 to my ruby friends) - write a faling test. Ctrl-0 - verify it
fails like you expected (Note: next on the hit list is to fix the SUnit
browser so it shows you the first error without having to do lots of
clicking and then run the debugger.. ). Then seeing the correct failing
test - press Ctrl-0 to put you back in your code to do more. Or - which I
know many people do (And I am getting more used to) - use the debugger to
fix the code. The flip back works particularly well when you want to make
sure you didn't break any tests. Flip over, make sure its green, flip back.

Actually in writing this - its made me think that its not a bad idea to be
able to flip to SUnit from any browser even if its not a test (in which case
it should just run the last one you had) just to make sure everything is
still running green.

This stuff probably should be in the base D6 image - as it works so well!

My package (without the additional idea) looks like this -

| package |
package := Package name: 'TDD'.
package paxVersion: 1;
 basicComment: 'Adds TDD support to the image.'.

package basicScriptAt: #postinstall put: '| bindings |

(Array with: ClassBrowserShell with: SystemBrowserShell)  do: [:shell|
 bindings := shell acceleratorKeyBindings.
 bindings at: ''Ctrl+0'' put: #runCurrentClassAsUnitTest.
 shell acceleratorKeyBindings: bindings]
!!

| bindings |

bindings := SUnitBrowser acceleratorKeyBindings.
bindings at: ''Ctrl+0'' put: #switchToLastBrowser.
SUnitBrowser acceleratorKeyBindings: bindings
!!'.
package basicScriptAt: #postuninstall put: '| bindings |

(Array with: ClassBrowserShell with: SystemBrowserShell with: SUnitBrowser )
do: [:shell|
 bindings := shell acceleratorKeyBindings.
 bindings removeKey: ''Ctrl+0'' ifAbsent: [].
 shell acceleratorKeyBindings: bindings]
!!'.

package methodNames
 add: #ClassBrowserAbstract -> #runCurrentClassAsUnitTest;
 add: #Object -> #isUnitTest;
 add: #SUnitAbsBrowser -> #switchToLastBrowser;
 add: 'TestCase class' -> #isUnitTest;
 yourself.

package binaryGlobalNames: (Set new
 yourself).

package globalAliases: (Set new
 yourself).

package setPrerequisites: (IdentitySet new
 add: '..\Object Arts\Dolphin\IDE\Base\Development System';
 add: '..\Object Arts\Dolphin\Base\Dolphin';
 add: '..\Camp Smalltalk\SUnit\SUnit';
 add: '..\odellsoft\SUnitBrowser\SUnitBrowser';
 yourself).

package!

"Class Definitions"!


"Global Aliases"!


"Loose Methods"!

!ClassBrowserAbstract methodsFor!

runCurrentClassAsUnitTest
 self selectedClass isUnitTest ifFalse: [^self].
 Smalltalk at: #LastBrowser put: self.
 classesPresenter runTests.
 "self setFocus"! !
!ClassBrowserAbstract categoriesFor:
#runCurrentClassAsUnitTest!commands!public! !

!Object methodsFor!

isUnitTest
 ^false! !
!Object categoriesFor: #isUnitTest!converting!private! !

!SUnitAbsBrowser methodsFor!

switchToLastBrowser
 Smalltalk at: #LastBrowser ifPresent: [ :browser| browser setFocus].
 ! !
!SUnitAbsBrowser categoriesFor: #switchToLastBrowser!accessing!private! !

!TestCase class methodsFor!

isUnitTest
 ^true! !
!TestCase class categoriesFor: #isUnitTest!public!Testing! !

"End of package definition"!

"Source Globals"!

"Classes"!

"Binary Globals"!


Reply | Threaded
Open this post in threaded view
|

Re: Really Cool TDD in D6

TimM-3
Actually if you want the newer behavior of switching to the last running
test suite - something slimy like the following works :-)

runCurrentClassAsUnitTest
 | testSuite |

 self selectedClass isUnitTest
  ifTrue: [testSuite := classesPresenter buildTestSuite]
  ifFalse:
   [Smalltalk at: #LastTestSuite ifAbsent: [^self].
   testSuite := Smalltalk at: #LastTestSuite].

 Smalltalk at: #LastBrowser put: self.
 Smalltalk at: #LastTestSuite put: testSuite.

 classesPresenter testBrowserClass sunitbShowAndRun: testSuite


"TimM" <[hidden email]> wrote in message
news:[hidden email]...

> There are a lot of possibilities to do really effective TDD in smalltalk -
> especially D6, in fact I'm really enjoying it. Someone on here pointed me
> in the right direction - adding an accelerator "Ctrl-0" to run your tests.
> Even better is to build on that tip and add another one to the SUnit
> browser to get you back.
>
> The feeling then becomes a lot like Eclipse and IntelliJ (how I've been
> selling D6 to my ruby friends) - write a faling test. Ctrl-0 - verify it
> fails like you expected (Note: next on the hit list is to fix the SUnit
> browser so it shows you the first error without having to do lots of
> clicking and then run the debugger.. ). Then seeing the correct failing
> test - press Ctrl-0 to put you back in your code to do more. Or - which I
> know many people do (And I am getting more used to) - use the debugger to
> fix the code. The flip back works particularly well when you want to make
> sure you didn't break any tests. Flip over, make sure its green, flip
> back.
>
> Actually in writing this - its made me think that its not a bad idea to be
> able to flip to SUnit from any browser even if its not a test (in which
> case it should just run the last one you had) just to make sure everything
> is still running green.
>
> This stuff probably should be in the base D6 image - as it works so well!
>
> My package (without the additional idea) looks like this -
>
> | package |
> package := Package name: 'TDD'.
> package paxVersion: 1;
> basicComment: 'Adds TDD support to the image.'.
>
> package basicScriptAt: #postinstall put: '| bindings |
>
> (Array with: ClassBrowserShell with: SystemBrowserShell)  do: [:shell|
> bindings := shell acceleratorKeyBindings.
> bindings at: ''Ctrl+0'' put: #runCurrentClassAsUnitTest.
> shell acceleratorKeyBindings: bindings]
> !!
>
> | bindings |
>
> bindings := SUnitBrowser acceleratorKeyBindings.
> bindings at: ''Ctrl+0'' put: #switchToLastBrowser.
> SUnitBrowser acceleratorKeyBindings: bindings
> !!'.
> package basicScriptAt: #postuninstall put: '| bindings |
>
> (Array with: ClassBrowserShell with: SystemBrowserShell with:
> SUnitBrowser ) do: [:shell|
> bindings := shell acceleratorKeyBindings.
> bindings removeKey: ''Ctrl+0'' ifAbsent: [].
> shell acceleratorKeyBindings: bindings]
> !!'.
>
> package methodNames
> add: #ClassBrowserAbstract -> #runCurrentClassAsUnitTest;
> add: #Object -> #isUnitTest;
> add: #SUnitAbsBrowser -> #switchToLastBrowser;
> add: 'TestCase class' -> #isUnitTest;
> yourself.
>
> package binaryGlobalNames: (Set new
> yourself).
>
> package globalAliases: (Set new
> yourself).
>
> package setPrerequisites: (IdentitySet new
> add: '..\Object Arts\Dolphin\IDE\Base\Development System';
> add: '..\Object Arts\Dolphin\Base\Dolphin';
> add: '..\Camp Smalltalk\SUnit\SUnit';
> add: '..\odellsoft\SUnitBrowser\SUnitBrowser';
> yourself).
>
> package!
>
> "Class Definitions"!
>
>
> "Global Aliases"!
>
>
> "Loose Methods"!
>
> !ClassBrowserAbstract methodsFor!
>
> runCurrentClassAsUnitTest
> self selectedClass isUnitTest ifFalse: [^self].
> Smalltalk at: #LastBrowser put: self.
> classesPresenter runTests.
> "self setFocus"! !
> !ClassBrowserAbstract categoriesFor:
> #runCurrentClassAsUnitTest!commands!public! !
>
> !Object methodsFor!
>
> isUnitTest
> ^false! !
> !Object categoriesFor: #isUnitTest!converting!private! !
>
> !SUnitAbsBrowser methodsFor!
>
> switchToLastBrowser
> Smalltalk at: #LastBrowser ifPresent: [ :browser| browser setFocus].
> ! !
> !SUnitAbsBrowser categoriesFor: #switchToLastBrowser!accessing!private! !
>
> !TestCase class methodsFor!
>
> isUnitTest
> ^true! !
> !TestCase class categoriesFor: #isUnitTest!public!Testing! !
>
> "End of package definition"!
>
> "Source Globals"!
>
> "Classes"!
>
> "Binary Globals"!
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Really Cool TDD in D6

Schwab,Wilhelm K
In reply to this post by TimM-3
Tim,

> There are a lot of possibilities to do really effective TDD in smalltalk -
> especially D6, in fact I'm really enjoying it. Someone on here pointed me in
> the right direction - adding an accelerator "Ctrl-0" to run your tests. Even
> better is to build on that tip and add another one to the SUnit browser to
> get you back.
>
> The feeling then becomes a lot like Eclipse and IntelliJ (how I've been
> selling D6 to my ruby friends) - write a faling test. Ctrl-0 - verify it
> fails like you expected (Note: next on the hit list is to fix the SUnit
> browser so it shows you the first error without having to do lots of
> clicking and then run the debugger.. ).

With plenty of gratitude for the SUnitBrowser, you thought is seconded.
  I use comments containing ready-made do-it using the
frequently-revised #prod: to simplify the process.  I use the browser to
locate failing tests, and use do-it to repeatedly run a given test.

IMHO, the Camp Smalltalk test runner is even harder to use than the
SUnit Browser; no doubt why the latter exists :)  I was surprised to
find that many people consider the runner's (sorry...) clumbsy user
interface to be a feature vs. a design flaw.  There is some discussion
in the Squeak mailing list archives, and it migh be worth reading
because they have a point.

If you are working the on the browser, please look for a problem with
list selection.  I frequently find that selecting a new item "on the
left" will lead to an errantly empty list "on the right".  Selecting
another item and returning will fix it, but it is quite distracting.  It
would also be great for the reset feature to (even optionally) preserve
selections.

Yes, I could fix these things, but I have found other ways of working
via #prod: and my filtered browser goodie which allows me to launch
fresh browsers on a limited number of tests.


> Actually in writing this - its made me think that its not a bad idea to be
> able to flip to SUnit from any browser even if its not a test (in which case
> it should just run the last one you had) just to make sure everything is
> still running green.

Maybe.  What if the test has potentially ugly side effects?  I am very
uneasy about anything involving the user interface.  Most of the time,
all is well, but it can be very easy to enter a recursive walkback
situation.  I would rather identify a stable state, save, perhaps
backup, and then run tests.

My general advice is to keep it simple.  Failing that, provide options
to disable things that might cause problems for some users.

Have a good one,

Bill


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Really Cool TDD in D6

TimM-3
>> Actually in writing this - its made me think that its not a bad idea to
>> be able to flip to SUnit from any browser even if its not a test (in
>> which case it should just run the last one you had) just to make sure
>> everything is still running green.
>
> Maybe.  What if the test has potentially ugly side effects?  I am very
> uneasy about anything involving the user interface.  Most of the time, all
> is well, but it can be very easy to enter a recursive walkback situation.
> I would rather identify a stable state, save, perhaps backup, and then run
> tests.

I don't understand why a test having ugly side effects would impact being
able to run the last test using Ctrl-0? If your test has side effects you
are worried about don't press Ctrl-0 (in fact don't write tests with side
effects).

I actually implemeted the run the last test from anywhere and its great! If
you refector a method - its good practice to run your tests again and make
sure everything is still green - so its handy to make changes in small steps
and just keep running your last suite regardless of what browser or class
you made the change in.

Definitely a top tip!

By the way - it demo's really nicely to the Ruby and Java and .Net crowd.
I've heard several people say "Whats that Smalltalk IDE thats like IntelliJ
again?". I think thats very cool that D6 would be compared in this way. So I
think Andy and Blair might have hit a sweet spot (but you need a few addins
like some of Ian's stuff and the test runner to get there. Also a few more
editor keystrokes would help too).

Tim


Reply | Threaded
Open this post in threaded view
|

Re: Really Cool TDD in D6

Schwab,Wilhelm K
Tim,

> I don't understand why a test having ugly side effects would impact being
> able to run the last test using Ctrl-0? If your test has side effects you
> are worried about don't press Ctrl-0 (in fact don't write tests with side
> effects).

That's nice to say, but not really practical (if it were, I would not
need the tests), especially for GUIs and of course for external
interfacing under development.  Complete meltdowns are rare, but they
can happen.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]