Although most of my time at The Job is spent in compiled languages, I have been trying to develop some skill in Python to enliven my technical skills.
This week, I got a chance to try something that I know would have been a real pain in a comp[iled language like C++.
The gist of the issue is that I want to automate some integration tests I'm writing for the system, so that I can just run them all with one command. I am trying to make them as modular as possible so that I can add new ones easily, since I know from past experience that if it takes any significant time to add tests, I will not have the time to add them. So I come up with a skeleton program that will run the tests, dividing them into preconditions that must pass, the test itself, and postconditions that must pass. Now I run into the issue that at the moment I do not want to package my tests, so I need to import the modules directly and individually. However, that makes it hard to add new tests, since the import list will grow with each test.
A quick search of www.python.org/documentation and I find the import statement is a shortcut for __import__(), and __import__() can take runtime strings as arguments. This means I can pass the test modules' names into the test skeleton. A little help from exec/eval and I can call an arbitrary function from my test module based on command line input.
Here's the code I have so far:
d = {}
with open(sys.argv[1]) as f:
for line in f:
(key, val) = line.split()
d[key] = val
execStmt1 = d['modulename'] + " = __import__('" + d['modulename'] + "', globals(), locals(), [], -1)"
execStmt2 = d['modulename'] + '.' + d['functionname'] + '(d)'
print execStmt1
print execStmt2
exec execStmt1
exec execStmt2
targetFunction = eval(d['modulename'] + '.' + d['functionname'])
And the data file sent in looks like this:
modulename dummy
functionname dummy2
arg1 1
arg2 2
And the dummy module dummy.py looks like this:
def dummy(arg1, arg2):
print "dummy(", arg1, ",",arg2,")"
def dummy2(d):
print "dummy2(",d['arg1'], ",", d['arg2'], ")"
if __name__ == '__main__':
dummy(0,0)
So this gets me most of the way there. I still need to rework how the preconditions and postconditions are run and their return values checked, and a few other things, but this was just so amazingly EASY to do, I thought it was worth a post
No comments:
Post a Comment