1

I've written a launcher/boilerplate python script that handles common initialization tasks for some network simulations I'm running. I'm having it dynamically load other python scripts that house the actual test code to run (defined in classes) based on cmdline args, and passing helper functions into the test battery code classes via a dictionary of lambdas.

Just to give you an idea, this is how the helper functions are being called:

self.helpers['createQueue'](switch=s1, port=3, qid=1, slice=700)
self.helpers['modFlow'](
    switch=s1, cmd='add', tableid=0,
    match='eth_type=0x800,ip_src=10.0.0.1,ip_dst=10.0.0.3',
    actions='nw_dec,output=3,queue=1'
)

Just to clarify, everything works. But I'm wondering if there's a more idiomatic way to approach this problem.

Calling the lambdas from the dictionary like this is a little hard to take in at first glance, and I'm really not convinced this approach is good coding practice.

Any thoughts would be appreciated. I'm picking up python as I go, so my knowledge of the language and practice is somewhat patchy at the moment.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • I haven't received any feedback, does my answer help you, or did I miss your main question? – Russia Must Remove Putin Aug 06 '15 at 21:59
  • I hadn't considered a unit test framework, not the kind of testing I usually associate with network simulations. I'm not testing code per se, but experimental extensions to the SDN control plane. I'll look into this when I can, I might be able to adapt it to my needs, but at the moment what we have works for us. What I'm really after is whether or not there's an elegant way to dynamically inject code from one namespace into another when the target isn't known beforehand. – jboley-arnl Aug 07 '15 at 12:57
  • I updated my answer. If I've answered your question, you can accept my answer by checking the checkmark next to it and it will add plus two to your rep on the site. Welcome to StackOverflow. Try to state your question as clearly as possible and be more responsive to attempts to help you in the future, and you'll get a better experience here, and soon be able to vote on content. Cheers! – Russia Must Remove Putin Aug 07 '15 at 13:42

1 Answers1

0

Have you seen the unittest module? This provides a framework to handle initializations, and there are options for test discovery. I'm going to demonstrate importing a target module and dynamically calling every function in it. Don't store lambdas in a dict, use named and documented functions in a regular namespace, like a module, and access them dynamically with dir() and getattr():

import target

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    def setUp(self):
        self.recreate_for_each_test = foo()

    def test_0(self):
        for name in dir(target): # probably use a try/except block here
            if condition(name) # define this condition 
                getattr(target, name)() # call dynamically

    def test_1(self):
        self.assertEquals(self.recreate_for_each_unit, foo())

    def test_2(self):
        with self.assertRaises(Exception):
             bar()

    def tearDown(self):
        self.recreate_for_each_unit.cleanup()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()

You'll probably want to handle exceptions with try/except, and get stack-traces where they fail. See this answer for more on that https://stackoverflow.com/a/31444861/541136

Community
  • 1
  • 1
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • Thanks for the help; it turns out that two modules can dynamically load each-other (cross-loading?) and use each other's classes and functions. Trying to perform a static import of functions from the boilerplate script, which is known at "compile time", consistently failed for some reason, but that's for another question. – jboley-arnl Aug 07 '15 at 15:08