Reputation: 31
I have two classes A and B with common behavior. Let's say I put the common stuff in a module that each class include
s:
class A
include C
def do_something
module_do_something(1)
end
end
class B
include C
def do_something
module_do_something(2)
end
end
module C
def module_do_something(num)
print num
end
end
(To begin with, is this a reasonable way to structure the classes/modules? From a Java background, I would have made C an abstract class that A and B both inherit from. However, I've read that Ruby doesn't really have a notion of an abstract class.)
What is a good way to write tests for this?
I could write tests for C, to specify its behavior for any class that include
s C. However, then my tests for A and B would only test the behavior that isn't in C. What if A's and B's implementations change so that they no longer use C? This just kind of feels funny because my description of A's behavior is split across two test files.
I could write tests only for A's and B's behavior. But then they will have a lot of redundant tests.
Upvotes: 0
Views: 930
Reputation: 340
Yes, this looks like a reasonable way to structure your code in Ruby. Typically, when mixing-in a module, you would define whether the module's methods are class or instance methods. In your example above, this could look like
module C
module InstanceMethods
def module_do_something(num)
print num
end
end
end
Then in your other classes, you would specify
includes C::InstanceMethods
(includes is used for InstanceMethods, extends is used for ClassMethods)
You can create tests in rspec using shared examples.
share_examples_for "C" do
it "should print a num" do
# ...
end
end
describe "A" do
it_should_behave_like "C"
it "should do something" do
# ...
end
end
describe "B" do
it_should_behave_like "C"
it "should do something" do
# ...
end
end
Example adopted from here. And here is another discussion site with some more info on shared examples.
Upvotes: 1