# Abstract Tests vs AutoRunner

**URL:** <https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835>\
**Category:** Ruby\
**Created:** [September 7, 2006, 3:07am UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835 "2006-09-07T03:07:28Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 3:07am UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/1 "2006-09-07T03:07:28Z")

</div>

Rubies:

I’m trying to get some elaborate test suites working via the hidden call  
to  
AutoRunner.

Because I can’t declare which suites to run, the system tests anything  
that  
derives from TestCase.

I want to do this:

class AbstractSuite \< Test::Unit::TestCase  
def test\_foo()  
p derive()  
end  
end

class ConcreteSuiteA \< AbstractSuite  
def derive()  
return ‘like this’  
end  
end

class ConcreteSuiteB \< AbstractSuite  
def derive()  
return ‘like that’  
end  
end

That’s the skeleton of the Abstract Test pattern, which is a major Good  
Thing. It prevents us from writing zillions of duplicate test cases with  
minimal differences between each one. For example, my derive() could  
return  
an object that must pass the same tests as another object, obeying  
Liskov  
Substitution Principle.

However, I can’t do it like that, because AutoRunner hoovers up every  
class  
derived from TestCase, and runs all of them as suites. I predictably get  
“test\_foo(AbstractSuite): NoMethodError: undefined method `derive’”

The ugly fix is this:

class ConcreteSuiteA \< Test::Unit::TestCase  
def test\_foo()  
p derive()  
end

```
def derive()
    return 'like this'
end

```

end

class ConcreteSuiteB \< ConcreteSuiteA  
def derive()  
return ‘like that’  
end  
end

That works, but it’s “not OO”. ConcreteSuiteB is not truly a derived  
version  
of ConcreteSuiteA.

So I’m asking this question because I don’t understand mixins, or  
AutoRunner, enough to fix this.

Could a mixin grant test cases to two concrete classes? Alternately,  
does  
AutoRunner have a feature to bump a suite from its list?

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 9:14am UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/2 "2006-09-07T09:14:03Z")

</div>

Indirectly answering your question, you could just define an empty  
derive method in your AbstractSuite.

class AbstractSuite \< Test::Unit::TestCase  
def test\_foo()  
p derive()  
end  
def derive; end  
end

Everything else remains the same, although the output from auto runner  
will be a bit screwy (3 tests in this case, rather than the expected  
2).

Chris

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 9:46am UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/3 "2006-09-07T09:46:15Z")

</div>

On 9/7/06, Phlip [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Could a mixin grant test cases to two concrete classes? Alternately, does  
> AutoRunner have a feature to bump a suite from its list?

Once TestCase is a class you cannot mix it in easily (or at least I  
think so). The reverse appproach would be much easier (to mix in your  
common behaviour)

AutoRunner has command line parameter -t that allows to exclude test  
case classes by a regex (-v /Abstract/). Another possibility is to  
extend AutoRunner to not load a TestClass that has any subclasses.

class Class  
def has\_subclasses?  
ObjectSpace.each\_object(Class) { |c| return true if self \> c }  
end  
end

Look for @filters in the AutoRunner code. You could copy the behaviour  
in -n and -t to add another parameter (e.g. --leaves-only) that will  
add to @filters \<\< Proc {|t| t (attached patch will do that)

Maybe you can even force the -t parameter

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 2:38pm UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/4 "2006-09-07T14:38:49Z")

</div>

“Phlip” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> Could a mixin grant test cases to two concrete classes? Alternately,  
> does AutoRunner have a feature to bump a suite from its list?

Indeed it can:

require ‘test/unit’

module AbstractSuite  
def test\_foo()  
p derive()  
end  
end

class ConcreteSuiteA \< Test::Unit::TestCase  
include AbstractSuite

```
def derive()
  return 'like this'
end

```

end

class ConcreteSuiteB \< Test::Unit::TestCase  
include AbstractSuite

```
def derive()
  return 'like that'
end

```

end

# \>\> Loaded suite -

# \>\> Started

# \>\> “like this”

# \>\> .“like that”

# \>\> .

# \>\> Finished in 0.000816 seconds.

# \>\>

# \>\> 2 tests, 0 assertions, 0 failures, 0 errors

If you define your shared tests in a module, you can then ‘include’ it  
in any number of suites derived from Test::Unit::TestCase.

-Marshall

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 6:29pm UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/5 "2006-09-07T18:29:32Z")

</div>

Chris R. wrote:

> class AbstractSuite \< Test::Unit::TestCase  
> def test\_foo()  
> p derive()  
> end  
> def derive; end  
> end

That would run test\_foo() with a stub. Because the real derive() is  
naturally important, this wouldn’t work. It’s also “not-OO”, because it  
isn’t minimal!

I could do it like that if I were building the suites from scratch, and  
then  
stubs would gracefully do nothing. But…

Nathaniel T. wrote:

> class ConcreteSuiteA \< Test::Unit::TestCase  
> include AbstractSuite

Jeeze Louise, could this friggin’ language ever make anything HARD?! I  
need  
to log hours doing SOMETHING!!!

---

<div class="post-metadata">

**Author:** ![Phlip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Phlip](https://www.ruby-forum.com/u/Phlip)\
**Post date:** [September 7, 2006, 2:42pm UTC](https://www.ruby-forum.com/t/abstract-tests-vs-autorunner/67835/6 "2006-09-07T14:42:49Z")

</div>

On 9/6/06, Phlip [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Rubies:

I resemble that remark!

> Could a mixin grant test cases to two concrete classes?

require ‘test/unit’

module AbstractSuite  
def test\_foo  
p derive  
end  
end

class ConcreteSuiteA \< Test::Unit::TestCase  
include AbstractSuite  
def derive  
return ‘like this’  
end  
end

class ConcreteSuiteB \< Test::Unit::TestCase  
include AbstractSuite  
def derive  
return ‘like that’  
end  
end

Outputs:

Loaded suite t  
Started  
“like this”  
.“like that”  
.  
Finished in 0.000483 seconds.

2 tests, 0 assertions, 0 failures, 0 errors

Which I think is what you’re looking for.

HTH,

–  
Nathaniel T.

\<:((\>\<
