Hi Jan,
as promised, here are some details about the class inheritance trouble I
ran into.
I wanted to have a intermediate class cockpit.CockpitTest that inherits
from avocado.test.Test, and then inherit our actual test classes from
cockpit.CockpitTest.
[ This might or might not be a good idea. In general I agree that
inheritance is a weak tool, but let's pretend for now that I really
need to have this inheritance chain.
]
This is the CockpitTest class:
# cockpit.py
from avocado import test
__all__ = [ 'CockpitTest' ]
class CockpitTest(test.Test):
pass
And this was my first try to use it:
#! /usr/bin/python
# test.py
from avocado import job
from cockpit import CockpitTest
class MyTest(CockpitTest):
def action(self):
self.log.info("Yay!")
if __name__ == "__main__":
job.main()
This leads to this error:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/avocado/test.py", line 332, in
action
raise NotImplementedError('Test subclasses must implement an action '
NotImplementedError: Test subclasses must implement an action method
The reason is that Avocado picks cockpit.CockpitTest as the class to
test, not MyTest. I believe this is essentially random: Avocado
enumerates all members of "test" and picks the first that is a subclass
of avocado.test.Test, which happens to be CockpitTest.
This variant of test.py fixes the problem:
#! /usr/bin/python
# test2.py
from avocado import job
import cockpit
class MyTest(cockpit.CockpitTest):
def action(self):
self.log.info("Yay!")
if __name__ == "__main__":
job.main()
Now CockpitTest is no longer a member of the "test" module, and Avocado
will not consider it.
Thus, the test resolution algorithm of Avocado seems to lead to
undefined behavior when there is more than one subclass of
avocado.test.Test.
I think the "one class-under-test per module" rule is fine, but maybe
Avocado could warn/fail when there is more than one?
Also, I didn't find a way to control the test resolution and tell
Avocado to ignore CockpitTest, or explicitly tell it to use MyTest.
The test2.py hack will work for now, but maybe Avocado could be improved
by only considering classes that have been defined in the same module
that it calls getmembers on.
https://github.com/avocado-framework/avocado/pull/474
Thanks!