Inheriting avocado.test.Test

Marius Vollmer marius.vollmer at redhat.com
Wed Mar 11 08:03:03 UTC 2015


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!


More information about the cockpit-devel mailing list