<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Jan 5, 2014 at 9:05 AM, Frank Shearar <span dir="ltr">&lt;<a href="mailto:frank.shearar@gmail.com" target="_blank">frank.shearar@gmail.com</a>&gt;</span> wrote:<br>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Oh, one nit with &quot;factoring the functionality such that testing is<br>

simple and effective&quot;: I find that by writing my tests first, I don&#39;t<br>
need to work hard to make things testable. Or the difficulty in<br>
writing the test in the first place leads to needing to separate the<br>
functionalities in the first place.<br></blockquote><div><br></div><div>Agreed. TDD is very powerful. </div><div><br></div><div>Here&#39;s an example from the Environments changes I just finished that may illustrate what I&#39;m talking about. EnvironmentTest has a bunch of tests that cover exports. Originally, they all looked something like this:</div>
<div><br></div><div><div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span>env export: #Griffle.</font></div><div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span>env at: #Griffle put: value.</font></div>
<div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span>self assert: (env public at: #Griffle) == value.</font></div></div><div><font face="georgia, serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Hard to get simpler than that, right? If  I export a name, then create a binding with that name, the binding shows up in the dictionary of public bindings. Testing Nirvana.</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">But then Levente points out that the implementation is flawed. I&#39;ve gotta make imports eager, which affects the way exports are implemented. And it turns out that, far from being the essence of the functionality, the &#39;public&#39; dictionary is an implementation detail, and now it&#39;s going away. All my tests are going to have to change. Ugh.</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">But I&#39;m in luck! After writing several tests like the one above, I had realized that the code the manipulates the environment always varies, but the last line, the assertion, is always the same. So I used Extract Method to create an assertion method called </font><font face="georgia, serif">#assertExports:value:</font><font face="arial, helvetica, sans-serif">. So when the time came to rewrite the environment implementation, the tests actually looked like this:</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="georgia, serif" size="4">testExplicitExport</font></div><div><div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span>env export: #Griffle.</font></div>
<div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span>env at: #Griffle put: value.</font></div><div><span style="font-family:georgia,serif;font-size:large;white-space:pre">        self assertExports: #Griffle value: value.</span><br>
</div><div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">        </span></font></div></div><div><font face="georgia, serif" size="4"><span class="" style="white-space:pre">assertExports: aSymbol value: anObject</span></font></div>
<div><span style="font-family:georgia,serif;font-size:large;white-space:pre">        </span><span style="font-family:georgia,serif;font-size:large">self assert: (env public at: aSymbol) == anObject.</span><font face="georgia, serif" size="4"><span class="" style="white-space:pre"><br>
</span></font></div><div><font face="georgia, serif" size="4"><br></font></div><div><font face="georgia, serif" size="4"><br></font></div><div><font face="arial, helvetica, sans-serif">All I had to do was change the assertion method to work like this:</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><font face="georgia, serif" size="4">assertExports: aSymbol value: v2<br></font></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div class="gmail_extra"><div class="gmail_quote"><font face="georgia, serif" size="4">| other |</font></div></div><div class="gmail_extra"><div class="gmail_quote"><font face="georgia, serif" size="4">other := Environment withName: #other.</font></div>
</div><div class="gmail_extra"><div class="gmail_quote"><font face="georgia, serif" size="4">other import: env.</font></div></div><div class="gmail_extra"><div class="gmail_quote"><font face="georgia, serif" size="4">self assert: (other bindingOf: aSymbol) value = v2</font></div>
</div></blockquote><div style="font-family:arial,helvetica,sans-serif"><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div style="font-family:arial,helvetica,sans-serif"><span style="font-family:arial,helvetica,sans-serif"><br>
</span></div><font face="arial, helvetica, sans-serif">That really does get to the essence of the functionality: if a name is exported from one environment, and imported into another one, the binding will be visible to methods compiled in the other environment. And those test were really helpful when it came to writing the new functionality. Hurray for testing!</font><div>
<font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Now, I used TDD here. In fact, I think I actually had the idea of a public dictionary when I was sitting there with an empty method pane trying to figure out what the first export test should be. But I still wrote a fragile, overly-coupled set of tests on my first attempt. This is what I meant by &quot;testing is hard.&quot; (Of course, I&#39;m also proving your point. If I hadn&#39;t used TDD at all, I could have easily ended up with a big mess that wasn&#39;t testable without stubbing out &quot;Smalltalk globals&quot;, disabling SystemChangeNotifier and subclassing Compiler.)</font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Here&#39;s something else I noticed while writing this: </font><font face="georgia, serif">#assertExports:value:</font><font face="arial, helvetica, sans-serif"> is not slick. In fact, it&#39;s downright awkward. But it&#39;s pretty easy to understand, because it follows the same pattern as #assert:equals:. The reader gets the gist, and if they need to see the details the implementation is right there in the test class, not some extension to Object. Also, it&#39;s scoped to this test class, other test classes aren&#39;t burdened with assertion methods that don&#39;t make sense for them.  </font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Finally, I think there&#39;s something to be said for awkwardness its self. There&#39;s value in the ordinariness of SUnit as Smalltalk code. I was saved from a bunch of tedious and possibly error-prone test rewriting because of my ordinary Smalltalk coding habits.  I noticed some duplication, extracted a method using the RB, and continued on my merry way. If I had been using some kind of slick assertion language, I&#39;m not sure I&#39;d have done that. </font></div>
<div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Colin</font></div><div><font face="arial, helvetica, sans-serif"><br></font><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div class="gmail_extra"><div class="gmail_quote"><div><font face="arial, helvetica, sans-serif"><br></font></div></div></div></blockquote></div></div></div>