Rusty Robot
Rusty Robot

Reputation: 1365

List of functions calls in python tests

I have an object

class Obj:
    def method1(self):
        print 'method1'

    def method2(self):
        print 'method2'

    def method3(self):
        print 'method3'

and function

def do_something():
    obj = Obj()
    obj.method2()
    obj.method1()
    obj.method3()

And I want to write test which tests do_something and Obj object. How can I receive list of methods which was called on obj without replacing (mocking) and changing obj behavior?

Something like

['method2', 'method1', 'method3']

Upvotes: 1

Views: 718

Answers (2)

Marcin
Marcin

Reputation: 49856

Use the trace package. See docs: http://docs.python.org/2/library/trace.html

From the docs:

import sys
import trace

# create a Trace object, telling it what to ignore, and whether to
# do tracing or line-counting or both.
tracer = trace.Trace(
    ignoredirs=[sys.prefix, sys.exec_prefix],
    trace=0,
    count=1)

# run the new command using the given tracer
tracer.run('main()')

# make a report, placing output in the current directory
r = tracer.results()
r.write_results(show_missing=True, coverdir=".")

Upvotes: 3

Brian
Brian

Reputation: 3131

You can create a generic Wrapper class which will encapsulate your object and track changes to it.

class Obj:
    def method1(self):
        print 'method1'

    def method2(self):
        print 'method2'

    def method3(self):
        print 'method3'

class Wrapper:
    def __init__(self, wrapped):
        self.calls = []
        self._wrapped = wrapped
    def __getattr__(self, n):
        self.calls.append(n)
        return getattr(self._wrapped, n)

By redefining __getattr__ we cause all attribute accessing on the wrapper to retrieve the attribute in the wrapped object. With the above defined I can do the following:

>>> obj = Obj()
>>> x = Wrapper(obj)
>>> x.calls
[]
>>> x.method2()
method 2
>>> x.method1()
method 1
>>> x.method3()
method 3
>>> x.calls
['method2', 'method1', 'method3']
>>> x.method1()
method 1
>>> x.method1()
method 1
>>> x.calls
['method2', 'method1', 'method3', 'method1', 'method1']

You can further improve __getattr__ in Wrapper to fit your needs. (record timestamps for the method calls, record output, log to a database, etc.)

Upvotes: 1

Related Questions