Arbitrary selection of functions

I am writing a test script that contains different functions for different tests. I would like to be able to randomly select a test to run. I have already achieved this with the following function ...

test_options = ("AOI", "RMODE")

def random_test(test_options, control_obj):
  ran_test_opt = choice(test_options)

  if ran_test_opt.upper() == "AOI":
     logging.debug("Random AOI Test selected")
     random_aoi()
  elif ran_test_opt.upper() == "RMODE":
    logging.debug("Random Read Mode Test selected")
    random_read_mode(control_obj)

However, I want to add additional test functions without having to change the selective testing function. All I would like to do is add to the test function to the script. In addition, I would also like to choose which test will be included in the random selection. This is what the test_options variable does. How can I change the random generation function to achieve this?

EDIT: I circumvented the fact that all tests might require different arguments by including them in the test class. All arguments will be passed to init, and testing functions will refer to them using the "I". when they need a specific variable ...

class Test(object):
  """A class that contains and keeps track of the tests and the different modes"""

  def __init__(self, parser, control_obj):
    self.parser = parser
    self.control_obj = control_obj

  def random_test(self):
    test_options = []
    for name in self.parser.options('Test_Selection'):
        if self.parser.getboolean('Test_Selection', name):
            test_options.append(name.lower())

    ran_test_opt = choice(test_options)
    ran_test_func = getattr(self, ran_test_opt)
    ran_test_func()

  #### TESTS ####
  def random_aoi(self):
    logging.info("Random AOI Test")
    self.control_obj.random_readout_size()

  def random_read_mode(self):
    logging.info("Random Readout Mode Test")
    self.control_obj.random_read_mode()
+4
source share
5 answers

You can create a list of functions in python that you can call:

test_options = (random_aoi, random_read_mode)

def random_test(test_options, control_obj):
    ran_test_opt = choice(test_options)
    ran_test_opt(control_obj) # call the randomly selected function

You must ensure that each function accepts the same arguments, so you can call them the same.

+3
source

If you need any human-readable names for functions, you can save them in the dictionary along with the function. I expect you to pass control_objeach function.

EDIT: by @Ikke, .

>>> test_options = {'AOI': random_aoi, 'RMODE': random_read_mode}

>>> def random_test(test_options, control_obj):
...    ran_test_opt = test_options[choice(test_options.keys())]
...    ran_test_opt(control_obj)

test_options.values(). "" list() , python 3.x, dict.values() .

>>> ran_test_opt = choice(list(test_options.values()))
+3

, . Python unittest. , :

import unittest

class Tests(unittest.TestCase):
    def test_something(self):
        ...
    def test_something_else(self):
        ...


if __name__ == '__main__':
    tests = list(unittest.defaultTestLoader.loadTestsFromTestCase(Tests))
    import random
    # repeat as many times as you would like...
    test = random.choice(tests)
    print(test)
    test()

, : unittest.main() - , , .

, . , unittest ( test). , , - , ..

+1
source

If you wrapped the test selection function and the tests themselves in the class, you can do the following:

from random import choice

class Test(object):
    """ Randomly selects a test from the methods with 'random' in the name """

    def random_aoi(self):
        print 'aoi'

    def random_read_mode(self):
        print 'read_mode'

    def random_text(self):
        print 'test'

    # add as many tests as needed here

    # important that this function doesn't have 'random' in the name(in my code anyway)
    def run_test(self): # you can add control_obj to the args 
        methods = [m for m in dir(self) if callable(getattr(self, m)) and 'random' in m]
        test = choice(methods)
        getattr(self, test)() # you would add control_obj between these parens also


app = Test()
app.run_test()

This makes it easy to add tests without having to change any other code. Here is information about getattr

0
source

In addition to other options, take a look functools.partial. This allows you to create closures for functions:

from functools import partial

def test_function_a(x,y):
   return x+y

def other_function(b, c=5, d=4):
   return (b*c)**d

def my_test_functions(some_input):
   funclist = (partial(test_function_a, x=some_input, y=4),
               partial(other_function, b=some_input, d=9))
   return funclist

random.choice(funclist)()

This allows you to normalize the argument list for each test function.

0
source

All Articles