How do I inherit abstract unit tests in Ruby?
The issue is that, as far as I can tell, Test::Unit
keeps track of which classes inherit from Test::Unit::TestCase
, and as a result, will only run tests from classes that directly inherit from it.
The way to work around this is to create a module with the tests you want, and then include that module in the classes that derive from Test::Unit::TestCase
.
require 'test/unit'
module TestsToInclude
def test_name
assert(self.class.name.start_with?("Concrete"))
end
end
class Concrete1 < Test::Unit::TestCase
include TestsToInclude
def test_something_bad
assert(false)
end
end
class Concrete2 < Test::Unit::TestCase
include TestsToInclude
def test_something_good
assert(true)
end
end
Output:
Loaded suite a
Started
.F..
Finished in 0.027873 seconds.
1) Failure:
test_something_bad(Concrete1) [a.rb:13]:
<false> is not true.
4 tests, 4 assertions, 1 failures, 0 errors
shell returned 1
how to write and inherit from an abstract subclass of ActionController::TestCase
I finally figured this out - once I realised that this is a general Ruby Test::Unit issue rather a Rails testing issue, a quick google instantly revealed How do I inherit abstract unit tests in Ruby? which already had a good answer. Then the only missing piece was being able to use the syntactic sugar:
test "something should behave in a certain way" do
...
end
rather than
def test_something_should_behave_in_a_certain_way" do
...
end
I found the answer to this within the ActiveSupport codebase itself, under lib/active_support/test_case.rb
:
extend ActiveSupport::Testing::Declarative
This module defines test
as a class method (which is why extend
is required rather than include
).
So the complete solution looks like this:
# tests/functional/admin/availabilities_controller_test.rb
class Admin::AvailabilitiesControllerTest < ActionController::TestCase
tests Admin::AvailabilitiesController
include Admin::ControllerTests
# non-reusable tests and helper methods specific to this
# controller test go here
end
# lib/admin/controller_tests.rb
module Admin::ControllerTests
extend ActiveSupport::Testing::Declarative
test "this test can be reused by anything which includes this module" do
...
end
end
The downside of this module-based approach is that you can't override the included tests. I guess that's just a fundamental limitation of Test::Unit - maybe the best answer is to move to RSpec, but I don't know it well enough yet to be sure.
Testing abstract classes in Rspec
One possibility is to use anonymous classes.
let(:fooMyClass) do
Class.new(MyClass) do
# ...
end
end
This way there is no need to do clean up.
Rails: Abstract Classes to apply to models
No, rails generators don't have this functionality, but you always can do it by yourself.
# app/models/creature.rb
class Creature
attr_accessor :eyes, :nose
end
# app/models/human.rb
class Human < Creature
end
# app/models/dog.rb
class Dog < Creature
end
Using strategy pattern in ruby unit testing
What I would do is create a base module with all the tests you want to run, and then initialize the objects in your derived classes. Something like this (using Ruby's built-in Test::Unit library):
module Testers
def test_something
assert_equal "expected result", @myobject.function_call
end
# ....
end
Then later on your actual test classes:
require 'test/unit'
class TestA < Test::Unit::TestCase
def setup
@myobject = A.new
end
include Testers
end
class TestB < Test::Unit::TestCase
def setup
@myobject = B.new
end
include Testers
end
The magic here is that using a mixin (combination of a module
and include
) you can have some of the nice aspects of multiple inheritance without actually having multiple inheritance.
c# How To test Inheritance of an Abstract class with protected methods with xunit
Using polymorphism, you will for sure be able to do as follows:
public class ClassB {
protected MethodB() {
}
}
public class ClassA : ClassB {
}
[TestFixture()]
public class TestA {
[Test()]
public void IsInstanceOfB() {
ClassA a = new ClassA();
Assert.IsInstanceOf(typeof(ClassB), a);
}
}
That is using NUnit, I guess there might be a similar approach with xUnit.
Ruby on Rails Single Table Inheritance (STI) and unit test problem (with PostgreSQL)
Turns out that the problem was due to the presence of:
./test/fixtures/technicians.yml
./test/fixtures/users.yml
This makes sense as the framework expected to be able to insert data into similarly named tables.
How do I run a Test::Unit suite to completion with a tally of tests/failures?
Some more background would be helpful. I can't say I understand the behavior you're seeing.
I'm using both the core test/unit lib that comes with ruby 1.8, as well as several versions of the gem with ruby 1.9. The normal behavior for both of these is to run the entire loaded suite to completion and summarize the results.
Running a script that says require 'test/unit'
will add an on-exit hook to run Test::Unit::AutoRunner
with a Test::Unit::Collector::ObjectSpace
collector (i.e. runs every instance of Test::Unit::TestCase
currently loaded in the global object space).
It's also fairly easy to write your own custom test runner which manually loads your test classes and packs them into a Test::Unit::TestSuite
, and capture its results.
But with every version of test/unit I've used, I've always seen the entire suite finish and report both failures and errors. In lieu of further info, I'd suggest experimenting with a single dummy test so see how you should expect test/unit to behave.
For example
require 'test/unit'
class Foo < Test::Unit::TestCase
def testFoo
flunk 'bad foo'
end
end
class Bar < Test::Unit::TestCase
def testBar
raise 'bar bar'
end
end
gives
Loaded suite foo
Started EF Finished in 0.001000 seconds.
1) Error:
testBar(Bar)
RuntimeError: bad bar
foo.rb:9:in `testBar`
2) Failure:
testFoo(Foo) [foo.rb:4]:
bad foo
2 tests, 1 assertions, 1 failures, 1 errors, 0 skips
Lastly: where are you trying to rescue/ensure? In the test methods? Under normal circumstances, there's no reason to catch an AssertionFailedError. This is for Test::Unit::TestCase
to do, as a way to count failures and give you the report you want. Catching this interferes with what test/unit is written to do.
unit-testing abstract classes and protected methods inside them
In order for you to test your abstract class you need to instantiate it. So create a class for testing purposes that inherits from your Component
(abstract) class.
Aside from the interfaces being used I don't see much to Mock.
Related Topics
Bash: /Home/Xxx/.Rvm/Scripts/Rvm: No Such File or Directory
Is the Unix Philosophy Falling Out of Favor in the Ruby Community
How to Select the Longest String from a Ruby Array
Building Hash by Grouping Array of Objects Based on a Property of the Items
How to See the Ruby Code in a Proc
Convert HTML to Plain Text (With Inclusion of <Br>S)
Rvm VS Native Installation of Ruby
What's the Cleanest Way to Override Activerecord's Find for Both Models and Collections
How to Beautify Xml Code in Rails Application
What Are Tainted Objects, and When Should We Untaint Them
Should I Deploy My Ruby on Rails Application on Heroku
How to Access the Base Namespace in Ruby