Loop cleanly through different classes If I have a number of different classes which manage certain tests. At the moment I have to launch each test individually which results in a lot of if statements.

I wonder if there is a way of putting all of these in a loop to manage the launching of each test and retrieving of results more cleanly.  Does anyone have any advice? Can anyone improve on this? Is this use of classes optimal (I'm not a professional programmer)?

class Engine(object):
    """Class that holds information about the
tests relevant to the engine"""

    def __init__(self):
        self.run = True # Flag to run the test or not
        self.kg = 20.5 # Some information required by this test
        self.ok = 'Not run' # Final result to say if the test was passed

class Wheels(object):
    """Class that holds information about the
tests relevant to the wheels"""

    def __init__(self):
        self.run = True
        self.number = 4
        self.ok = 'Not run'

class Door(object):
    """Class that holds information about the
tests relevant to the doors"""

    def __init__(self):
        self.run = True
        self.colour = 'red'
        self.ok = 'Not run'

class Car(object):
    """Class that holds information about the
different tests available"""

    def __init__(self):
        self.engine = Engine()
        self.wheels = Wheels()
        self.door = Door()

motor = Car()

if motor.engine.on is True:
    import engine_tests # An external file containing everything about engine tests
    motor.engine.ok = engine_tests.launch(weight=motor.engine.kg) # Return success/failure of tests

if motor.wheels.on is True:
    import wheel_tests
    motor.wheels.ok = wheel_tests.launch(nwheels=motor.wheels.number)

if motor.door.on is True:
    import door_tests
    motor.door.ok = door_tests.launch(shading=motor.door.colour)

print 'Tests completed'
print 'Engine: ', motor.engine.ok
print 'Wheels: ', motor.wheels.ok
print 'Door: ', motor.door.ok
The params for testing are different from each object, so I think this part should be put in the classes and present a uniform interface, this is what classes are about.

I suggest 2 versions: either you only put the params needed for test in the classes, or (better in my opinion), you put the entire call to the test in the classes. With some syntactic sugar, this leads to

Only the test data in the classes

class Engine(object):
    """Class that holds information about the
tests relevant to the engine"""

    def __init__(self):
        self.run = True # Flag to run the test or not
        self.kg = 20.5 # Some information required by this test
        self.ok = 'Not run' # Final result to say if the test was passed

    def get_test_params(self):
        return { 'weight': self.kg }

class Wheels(object):
    """Class that holds information about the
tests relevant to the wheels"""

    def __init__(self):
        self.run = True
        self.number = 4
        self.ok = 'Not run'

    def get_test_params(self):
        return { 'nwheels': self.number }

class Door(object):
    """Class that holds information about the
tests relevant to the doors"""

    def __init__(self):
        self.run = True
        self.colour = 'red'
        self.ok = 'Not run'

    def get_test_params(self):
        return { 'shading': self.colour }

class Car(object):
    """Class that holds information about the
different tests available"""

    def __init__(self):
        self.engine = Engine()
        self.wheels = Wheels()
        self.door = Door()

motor = Car()

for partName in 'engine wheels door'.split():
    part = getattr(motor, partName)
    part.on = True # So the test is run (everything is off in your example)
    if part.on: # No need to write "is True", this is what "if" is about
        test_module = __import__(partName + '_tests')
        part.ok = test_module.launch(**part.get_test_params())

print 'Tests completed'
print 'Engine: ', motor.engine.ok
print 'Wheels: ', motor.wheels.ok
print 'Door: ', motor.door.ok


Running the test from the classes

class Engine(object):
    """Class that holds information about the
tests relevant to the engine"""

    def __init__(self):
        self.run = True # Flag to run the test or not
        self.kg = 20.5 # Some information required by this test
        self.ok = 'Not run' # Final result to say if the test was passed

    def run_test(self):
        import engine_tests
        return engine_tests.launch(weight=self.kg)

class Wheels(object):
    """Class that holds information about the
tests relevant to the wheels"""

    def __init__(self):
        self.run = True
        self.number = 4
        self.ok = 'Not run'

    def run_test(self):
        import wheels_tests
        return wheels_tests.launch(nwheels=self.number)

class Door(object):
    """Class that holds information about the
tests relevant to the doors"""

    def __init__(self):
        self.run = True
        self.colour = 'red'
        self.ok = 'Not run'

    def run_test(self):
        import door_tests
        return door_tests.launch(shading=self.colour)

class Car(object):
    """Class that holds information about the
different tests available"""

    def __init__(self):
        self.engine = Engine()
        self.wheels = Wheels()
        self.door = Door()

motor = Car()

for partName in 'engine wheels door'.split():
    part = getattr(motor, partName)
    part.on = True # So the test is run (everything is off in your example)
    if part.on: # No need to write "is True", this is what "if" is about
        part.ok = part.run_test()

print 'Tests completed'
print 'Engine: ', motor.engine.ok
print 'Wheels: ', motor.wheels.ok
print 'Door: ', motor.door.ok


If there's only one car, the last part can become:

for part in (motor.engine, motor.wheels, motor.door):
    part.on = True # So the test is run (everything is off in your example)
    if part.on: # No need to write "is True", this is what "if" is about
        part.ok = part.run_test()