<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Wood for the Trees: ActiveTest: Examination, Part IV: Salvaging Useful Ideas</title>
    <link>http://www.mathewabonyi.com/articles/2007/01/01/activetest-examination-part-iv-salvaging-useful-ideas</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>struggling to dig life</description>
    <item>
      <title>ActiveTest: Examination, Part IV: Salvaging Useful Ideas</title>
      <description>&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt; and Abstraction:&lt;/strong&gt; There is a difference between practices of &lt;span class="caps"&gt;DRY&lt;/span&gt; and Abstraction. When you are being &lt;span class="caps"&gt;DRY&lt;/span&gt;, you are either addressing a new repetition or continuing an earlier practice. The primary focus of being &lt;span class="caps"&gt;DRY&lt;/span&gt; is &lt;em&gt;not&lt;/em&gt; to create higher level tools for future use. It is a practice of improving past and present code. It replaces, deletes, compresses, encapsulates&amp;#8212;it is passive redesign. Abstraction, on the other hand, is active design. When you try to be &lt;span class="caps"&gt;DRY&lt;/span&gt; without a real model, you are actually abstracting. The process of abstraction is a wider programming activity which can lead quite naturally into over-design, because without real models and implementation, it often fails to address real issues.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p style="text-align:justify;"&gt;With that short sermon, let&amp;#8217;s make ActiveTest useful again. As I mentioned in the introduction to this mini-series, there are things to take away from the old version of ActiveTest. We&amp;#8217;ll now look at them in full and show why they are still useful.&lt;/p&gt;


	&lt;h4&gt;1. Test::Unit inheritance: filtering classes&lt;/h4&gt;


	&lt;p style="text-align:justify;"&gt;One of the few patches in the old ActiveTest is to modify Test::Unit&amp;#8217;s very well hidden collector filter. The idea of filtration is critical to making inheritance possible. If you have a situation where many ActiveRecord models share many attributes, for example in a Single Table Inheritance for a &amp;#8216;Content&amp;#8217; model, and they all have a body, title, excerpt, owner, created_at, created_by, updated_at and updated_by, the tests for these attributes will be identical across all model tests. So why not create a &amp;#8216;ContentTestCase&amp;#8217; suite which each model test inherits? With Test::Unit you can make a &amp;#8216;StandardContentTests&amp;#8217; module and mix it in, but then you are looking for a place to put them and later looking around for those abstracted tests. Alternatively, if you want to use inheritance, those tests will be run immediately. You want to filter out the abstract class, but still be able to inherit from it. By modifying Test::Unit&amp;#8217;s collector filter, it is possible to put anything in the ActiveTest namespace and it will not be run:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;test/unit/autorunner&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test::Unit::AutoRunner&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize_with_scrub&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;standalone&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;initialize_without_scrub&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;standalone&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@filters&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;proc&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^ActiveTest::&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;class&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;alias_method&lt;/span&gt; &lt;span class="symbol"&gt;:initialize_without_scrub&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:initialize&lt;/span&gt;
  &lt;span class="ident"&gt;alias_method&lt;/span&gt; &lt;span class="symbol"&gt;:initialize&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:initialize_with_scrub&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p style="text-align:justify;"&gt;I won&amp;#8217;t go on about the peculiarity of having the filter in AutoRunner, but the inaccessibility of the filter requires a monkey patch like the one above. Just poking into &lt;code&gt;initialize&lt;/code&gt; lets us add to the @filters instance variance on AutoRunner and tell it to ignore the ActiveTest namespace. This technique is more about just reading through the code and finding the right place to patch.&lt;/p&gt;


	&lt;h4&gt;2. Metaprogramming techniques (not all of them)&lt;/h4&gt;


	&lt;p style="text-align:justify;"&gt;Wrapping &lt;code&gt;define_method&lt;/code&gt; has proven to be pretty pointless other than ensuring an unique method name, but developing a lower-level language to standardise class-level macros is a general idea which ActiveTest could keep with some minor adjustments. Ignoring what &lt;code&gt;define_behavioral&lt;/code&gt; does, this is a very short macro definition (from &lt;code&gt;ActiveTest::Controller&lt;/code&gt;):&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;assigns_records_on&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{})&lt;/span&gt;
    &lt;span class="ident"&gt;define_behavioral&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:assign_records_on&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;send&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;call_&lt;span class="expr"&gt;#{action}&lt;/span&gt;_action&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;assert_assigned&lt;/span&gt;&lt;span class="punct"&gt;((&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:with&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;plural_or_singular&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;)).&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p style="text-align:justify;"&gt;If &lt;code&gt;define_behavioral&lt;/code&gt; is made to register behaviors for a better parsing method than using &lt;code&gt;method_missing&lt;/code&gt;, then we give it some meaning, but not really enough to keep it. The rest of the method definition, however, is quite clean for creating macros for Subjects, especially if it is compressed in the way mentioned in &lt;a href="http://www.mathewabonyi.com/articles/2007/01/01/activetest-examination-part-iii-code-bloat/"&gt;Part &lt;span class="caps"&gt;III&lt;/span&gt;&lt;/a&gt;. Making test macros, however, needs to be dropped in the way it is being used here, or at least used more sparingly. We could keep the &lt;code&gt;setup&lt;/code&gt; macro because it sets up useful instance variables and makes reasonable guesses about the test suite&amp;#8217;s environment. So, the macro idea should be kept back for special cases, the current implementation entirely dropped.&lt;/p&gt;


	&lt;h4&gt;3. Nested, self-contained setup methods through &lt;del&gt;sorcery&lt;/del&gt; method unbinding &amp;#38; stacking&lt;/h4&gt;


	&lt;p style="text-align:justify;"&gt;I can&amp;#8217;t help but be partial to the way I nested setup and teardown methods. It is my first actually useful innovation in Ruby&amp;#8212;a trickery of method unbinding and stacking. Perhaps this bias makes me think it is still useful, but I honestly think it is a useful way to wrap Test::Unit. Let&amp;#8217;s have a look at the way it is done in &lt;code&gt;ActiveTest::Base&lt;/code&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;class_inheritable_array&lt;/span&gt; &lt;span class="symbol"&gt;:setup_methods&lt;/span&gt;
  &lt;span class="ident"&gt;class_inheritable_array&lt;/span&gt; &lt;span class="symbol"&gt;:teardown_methods&lt;/span&gt;

  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setup_methods&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;teardown_methods&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;

  &lt;span class="comment"&gt;# Execute all defined setup methods beyond Test::Unit::TestCase.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;setup_with_nesting&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setup_methods&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;alias_method&lt;/span&gt; &lt;span class="symbol"&gt;:setup&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:setup_with_nesting&lt;/span&gt;

  &lt;span class="comment"&gt;# Execute all defined teardown methods beyond Test::Unit::TestCase.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;teardown_with_nesting&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;teardown_methods&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;method&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;alias_method&lt;/span&gt; &lt;span class="symbol"&gt;:teardown&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:teardown_with_nesting&lt;/span&gt;

  &lt;span class="comment"&gt;# Suck in every setup and teardown defined, unbind it, remove it and&lt;/span&gt;
  &lt;span class="comment"&gt;# execute it on the child. From here on out, we nest setup/teardown.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.method_added&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;symbol&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="constant"&gt;ActiveTest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
      &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;symbol&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;setup&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
        &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setup_methods&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;instance_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:setup&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;
        &lt;span class="ident"&gt;remove_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:setup&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;teardown&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
        &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;teardown_methods&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;instance_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:teardown&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;
        &lt;span class="ident"&gt;remove_method&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:teardown&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p style="text-align:justify;"&gt;The first aspect which is useful is allowing setup and teardown nesting without affecting additions to Test::Unit made before or after loading ActiveTest. This is allowed by the code in &lt;code&gt;method_added&lt;/code&gt;. Before ActiveTest is loaded, the methods and aliases already exist on Test::Unit; after ActiveTest is loaded, all setup or teardown methods are stacked in a class inherited array and subsequently undefined from the original class. When setup is finally called on a subclass of ActiveTest::Base, it is the ActiveTest::Base method called first. Here is an example stack:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test::Unit::TestCase&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;setup&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test::Unit::TestCase&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;setup_with_fixtures&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;b&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;alias_method_chain&lt;/span&gt; &lt;span class="symbol"&gt;:setup&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:fixtures&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ActiveTest::Sample&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveTest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;setup&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SampleTest&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveTest&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Sample&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;setup&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;d&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p style="text-align:justify;"&gt;Upon execution, it will output: &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, then &lt;code&gt;a&lt;/code&gt;. A caveat of this technique is that you must be absolutely certain that each unbound method &lt;code&gt;setup_with_nesting&lt;/code&gt; executes must be rebound to the original class or one of its descendants. Because of the way class inherited attributes work, this rule is not violated: &lt;code&gt;SampleTest&lt;/code&gt; can run the setup method from &lt;code&gt;ActiveTest::Sample&lt;/code&gt; because it is a descendant, but other classes inheriting from &lt;code&gt;ActiveTest::Sample&lt;/code&gt; will not have methods from &lt;code&gt;SampleTest&lt;/code&gt;.&lt;/p&gt;


	&lt;h4&gt;4. Specificity of breaking down things into Subjects&lt;/h4&gt;


	&lt;p style="text-align:justify;"&gt;This is more of a design note than actual programming. Presently in Test::Unit, it is only possible to add to Test::Unit::TestCase, from which every test suite inherits. There is no way to say that, for example, &lt;code&gt;assert_difference&lt;/code&gt; for an ActiveRecord test is slightly different to &lt;code&gt;'assert_difference&lt;/code&gt; for an ActionController test. The functionality may be the same (for example, refreshing the Record or refreshing the Controller request), but implemented differently for each. By creating subclasses of a test suite that provide only the methods needed by that kind of test, the developer can easily encapsulate test methods and not leak public methods across different kinds of tests. It&amp;#8217;s just cleaner and will definitely form the backbone of test suites in the new ActiveTest framework.&lt;/p&gt;


	&lt;p style="text-align:justify;"&gt;&lt;strong&gt;Coming Up Next: Redesigning Weak Areas&amp;#8230;&lt;/strong&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 01 Jan 2007 23:13:42 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:8d6c2546-429c-4592-bcfe-5c1dc07e9f64</guid>
      <author>Mathew Abonyi</author>
      <link>http://www.mathewabonyi.com/articles/2007/01/01/activetest-examination-part-iv-salvaging-useful-ideas</link>
      <category>Discoveries</category>
      <category>Ruby</category>
      <category>Rails</category>
      <category>Plugins</category>
      <trackback:ping>http://www.mathewabonyi.com/articles/trackback/37</trackback:ping>
    </item>
  </channel>
</rss>
