how to optimize the below code with a helper function
Martin A. Brown
martin at linux-ip.net
Mon Apr 4 10:07:20 EDT 2016
Greetings (again) Ganesh,
I notice that you ask about how to optimize the code, but I think
what you mean is you want simpler code that is less repetitive and
less copy/paste error-prone. Is that correct?
Below, I make a few suggestions about how to simplify, although,
there probably is further simplification that could be done.
>I am on python 2.7.10 and Linux.
Noted. I tested my answer to your question on a Python 2.7, as
well.
>I have a python function where the similar kind of pattern
>repeating 100 of times
When you have a repetitive sequence of operations (or test cases, it
looks like), you can often figure out a way to store the parameters
as data. When the parameters become data, then, the code becomes
simpler.
>Sample code snippet:
>
>test01_log = os.path.join(LOG_DIR, "test01.log")
> cls.get_baddr['test01'] = failure.run_tool(
> test01_log, object="inode", offset="18", size="4",
> optype="set")
>
>test02_log = os.path.join(LOG_DIR, "test02.log")
> cls.get_baddr['test02'] = failure.run_tool(
> test02_log, lin=lin_02, object="lin", offset="100", size="5",
> optype="set")
> ..............................................------------------------
>
>test100_log = os.path.join(LOG_DIR, "test100.log")
> cls.get_baddr['test100'] = failure.run_tool(
> test02_log, baddr=lin_02, object="baddr", offset="100", size="5",
> optype="set")
I observe that here in the failure.run_tool() call, the logfile is
test02_log. I would have expected it to be test100_log. I'm
guessing that this is exactly the sort of copy/paste error that you
wish to avoid.
>(1) Any tips how I can optimize this i.e test case, should have a helper
>function that all test cases call.
One function that jumps out very easily (to my eye) is a function to
create the logfile name from the test case name. You will see how I
do that in the sample, so that you can call the run_tool function as
you are currently calling it.
(You might consider putting the logfile name generation into the
run_tool function, though, in which case, run_tool gets even simpler
and you can get rid of my function, addLogFilename. Hopefully, that
makes sense to you....)
>(2) Also note that failure.run_tool function can have variable
>number of argments how to handle this in the helper function?
A variable number of arguments: this seems like the perfect case
for using keyword arguments!
https://docs.python.org/2/tutorial/controlflow.html#keyword-arguments
I have one additional observation about your sample code, Ganesh.
When I read this:
cls.get_baddr['test01'] = failure.run_tool(
test01_log, object="inode", offset="18", size="4",
optype="set")
I am guessing that you are calling an external program in your test.
I also notice that you have string contents in your variables, for
example, offset="18". (That's part of why I guess you are calling
an external program as part of your test.)
If you are calling an external command in 'run_tool', why not put
the exact command-line you want to execute into the test data.
This would simplify your code and makes the test more transparent,
as well.
d = dict()
d['test01'] = dict(cmd=['some_command', '--offset', '18', '--size', '4'],
optype="set", object='inode')
Then, in run_tool, something like this:
subprocess.Popen(cmd, shell=False, stderr=logfile)
But, these suggestions are all, basically, different riffs on the
same basic idea:
Where you have many testing scenarios, try to figure out a way to
store all of the test cases in data and then have the test runner
operate on the data.
Good luck,
-Martin
#! /usr/bin/python
from __future__ import absolute_import, division, print_function
import os
import sys
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logger = logging.getLogger(__name__)
LOG_DIR = '/var/log/frobnitz'
def createTestCases(LOG_DIR):
'''create a test case data dictionary with parameters'''
d = dict()
d['test01'] = dict(object="inode", offset="18", size="4", optype="set")
lin_02 = "something"
d['test02'] = dict(object="lin", lin=lin_02, offset="18", size="5",
optype="set")
d['test100'] = dict(object="baddr", baddr=lin_02, offset="100", size="5",
optype="set")
return addLogFilename(d, LOG_DIR)
def run_tool(logfile, **kw):
logger.info('%s would execute with %r', logfile, kw)
def addLogFilename(d, logdir):
'''put the logfile name into the test case data dictionary'''
for casename, args in d.items():
args['logfile'] = os.path.join(logdir, casename + '.log')
return d
def main():
testcases = createTestCases(LOG_DIR)
get_baddr = dict()
for casename, kw in testcases.items():
# -- yank the logfile name out of the dictionary, before calling func
logfile = kw.pop('logfile')
get_baddr[casename] = run_tool(logfile, **kw)
if __name__ == '__main__':
main()
# -- end of file
--
Martin A. Brown
http://linux-ip.net/
More information about the Python-list
mailing list