I am writing a test, where I create a constructor.
This constructor has one parameter, which I pass a Mock inside.
But except for this parameter, there is another function inside of the parameter and I'm not sure how to get the constructor to see it as a Mock.
Here's an easy example:
Class MyClass():
def __init__(self, var):
self._var = var
self._func()
# Other stuff, I actually care about and can easily check **
Now it's easy to handle the var if I pass it as a parameter in the test:
def test_trying_mock(self):
var = MagicMock()
object = MyClass(var)
And the var line is handled. How can I make the constructor see func as mock and make it skip it to the part I actually wanna run and check?
After some research I found out how to do it:
In the testing class, under set_up, I added self._mock_func().
Outside of set_up, I implemented this function like this:
def _mock_func(self):
class_path = ' [path to MyClass] '
self._func_mock = self.mock_object('_func', path= class_path)
Then, when the constructor runs, it will give this function a mock and keep running.
Related
Asking just out of curiosity:
Intuitively, I would tend to think that the code below would fail because the __init__ function calls somefunc to populate somevar before the function was defined in the object's body, as would be the case for functions within a module.
Could you explain why this code actually works?
Thanks,
class someobj:
def __init__(self):
self.somevar = self.somefunc()
def somefunc(self):
return 'some_value'
obj = someobj()
print(obj.somevar)
Calling def assigns the function code, variables etc to its name, but doesn't run the internal code. Documentation.
The interpretater looks at this script and says
I'll define a class (basically a namespace)
Inside the class, I'll DEFINE class.init
Another define call; I'll DEFINE class.somefumc
Now the init is called by the constructor and the somefunc method is already defined.
I am trying to unit test a block of code, and I'm running into issues with mocking the object's type to grab the right function from a dictionary.
For example:
my_func_dict = {
Foo: foo_func,
Bar: bar_func
FooBar: foobar_func
}
def generic_type_func(my_obj):
my_func = my_func_dict[type(my_obj)]
my_func()
With this code, I can swap between functions with a key lookup, and it's pretty efficient.
When I try to mock my_obj like this, I get a KeyError:
mock_obj = Mock(spec=Foo)
generic_type_func(mock_obj)
# OUTPUT:
# KeyError: <class 'unittest.mock.Mock'>
Because it's a mock type. Although, when I check isinstance(), it returns true:
is_instance_Foo = isinstance(mock_obj, Foo)
print(is_instance_foo)
# Output:
# True
Is there any way to retain the type() check, and using the dictionary lookup via a key, while still maintaining the ability to mock the input and return_type? Or perhaps a different pattern where I can retain the performance of a dictionary, but use isinstance() instead so I can mock the parameter? Looping over a list to check the type against every possible value is not preferred.
I managed to unit test this by moving the function to the parameter itself, and implicitly calling the function from the parent. I wanted to avoid this, because now the function manipulates the parent implicitly instead of explicitly from the parent itself. It looks like this now:
def generic_type_func(self, my_obj):
my_obj.my_func(self)
The function then modifies self as needed, but implicitly instead of an explicit function on the parent class.
This:
def my_func(self, parent):
self.foo_prop = parent
Rather than:
def my_foo_func(self, foo):
foo.foo_prop = self
This works fine with a mock, and I can mock that function easily. I've just hidden some of the functionality, and edit properties on the parent implicitly instead of explicitly from within the class I'm working in. Maybe this is preferable anyways, and it looks cleaner with less code on the parent class. Every instance must have my_func this way, which is enforced via an abstract base class.
Trying to determine if I should try to use decorator or some other Pythonic way to reduce code that many of my functions are doing. I would like these functions to be able to call just maybe one other function at the start of each function or somehow "decorate" the start of each function. I have never used decorator before and am struggling to implement this decorate idea in a pythonic way to reduce the common set of share code at each function.
I have many functions that will perform the same set of steps at the start of the function. However, there is some structure concerns of the common code that makes this "decorator" idea difficult :
The functions are all in child class of a parent class.
The common commands between the functions reference variable names
that are specific to the function (but a subset of the function
name).
The common commands need to return to the caller and not execute any
more of the child function if a certain condition is met. ("if jobj : " block in the sample code)
For variable/attribute examples, child function get_nas_server(self) will utilize "nas_server" variable variants in the common set of code. Subtracting the get_ from the function name reveals the base of the variable name to be used in the common set of code. Example variables names and object attributes derived from "get_nas_server" function name:
nas_server
nas_server.json
self.nas_server (attribute)
Here is the common code from one of the functions:
####################################################################
def get_nas_server(self):
####################################################################
"""\nGets COMMAND nas_server and places data into self.nas_server"""
try:
self.nas_server
return self.nas_server
except AttributeError:
pass
self.get_file_cmd('nas_server')
jobj = self.fresh_json('nas_server.json')
if jobj :
self.nas_server = jobj
return self.nas_server
self.get_file_cmd('get_nas_server')
Everything below that code above in the function is specific to the function purpose and not appropriate for discussion here. Basically I am trying to make all that code above reusable in my functions, but the code has to have the variables and attribute changed depending on the function name.
Thanks for reading if you got this far and thanks for all help.
Seems like something you could define as a helper method in the parent class:
class Parent(object):
def _get_something(name):
try:
return getattr(self, name)
except AttributeError:
pass
self.get_file_cmd(name)
jobj = self.fresh_json(name+'.json')
if jobj :
setattr(self, name, jobj)
return jobj
self.get_file_cmd('get_'+name)
As this snippet demonstrates, you can use the getattr(), setattr() and hasattr() functions to reference object attributes by name.
You can use a decorator inside your class, if the initial bookkeeping stuff is too specific to that class. Everytime you need to do that initial check inside a class method, you can simply decorate it with the auto_nas decorator I have added below. The scope of this wrapper, I am assuming, is specific to this class alone. Otherwise, you can move it outside the class for generality, but remember to change (self=None) if you're going to do so.
class YourMainClass():
# This is your main class inside which all the methods are defined.
def auto_nas(func):
# This wrapper function will be called instead of your class methods.
def wrap(self):
# All your bookkeeping stuff goes here.
try:
self.nas_server
return self.nas_server
except AttributeError:
pass
self.get_file_cmd('nas_server')
jobj = self.fresh_json('nas_server.json')
if jobj :
self.nas_server = jobj
return self.nas_server
self.get_file_cmd('get_nas_server')
# Things went well - we shall call the actual method.
return func(self)
return wrap
#auto_nas
def get_nas_server(self):
# This is one of your methods that require bookkeeping
pass
Also, notice the self inside the wrapper function. It is automatically passed as an argument by Python, and thus you can access all the instance specific attributes from inside that decorator. Once again, this is appropriate if your decorator must do jobs specific to each instances of your class. If that is not the case, you can simply put all of that code in a function and call it each time whenever you want.
Much thanks to Augurar for pointing in the proper direction. I ended up created a stub method in the parent class. Just needed to call the method with the proper technique to "extend" the parent method. Then calling that stub method from the child class with super() There must be a proper name for this technique? method override? method extend?
Here is the parent class method mostly as Augurar suggested:
###########################################################################
def get_stub(self,fcmd):
###########################################################################
try:
return getattr(self, fcmd)
except AttributeError:
pass
jobj = self.fresh_json(fcmd + '.json')
if jobj :
setattr(self, fcmd, jobj)
return jobj
if not self.get_file_cmd(fcmd):
self.log.error("{} not found".format(fcmd))
return False
Here is the manner in which the child method uses this parent method:
####################################################################
def get_nas_server(self):
####################################################################
super().get_stub('nas_server')
#bunch of child method specific code below here
I am trying to set a static variable inside a function. Essentially, I want this variable to be false initially. After the first time this function is called, I want the variable to be set to true.
I currently have the following:
class LKTracker(object):
def track_points(self,width,height):
if not hasattr(track_points, "gotInitialFeatures"):
track_points.gotInitialFeatures = None
if not track_points.gotInitialFeatures:
#do some stuff
track_points.gotInitialFeatures = True
With this code, I keep receiving the following error:
NameError: global name 'track_points' is not defined
Anyone know what is happening here?
In a global function, you can refer directly to the function object by looking up the name.
This does not work in a method; you'd have to look the method up on the class instead:
LKTracker.track_points
This still won't do what you want, however, because you'd get a unbound method object at that moment:
>>> LKTracker.track_points
<unbound method LKTracker.track_points>
Method objects are created on demand (because functions are descriptors), and creating an attribute on a method object is futile; they generally only live for a short while.
You'd need to access the function instead:
>>> LKTracker.track_points.__func__
<function track_points at 0x103e7c500>
but you can do the same thing on self:
self.track_points.__func__
Now you can add a attribute:
track_points = self.track_points.__func__
if not hasattr(track_points, "gotInitialFeatures"):
track_points.gotInitialFeatures = None
if not track_points.gotInitialFeatures:
#do some stuff
track_points.gotInitialFeatures = True
But it would be much easier to just store that attribute on the class instead:
if not hasattr(LKTracker, 'gotInitialFeatures'):
You shall init static variable before call a function.
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
and now you can:
#static_var("gotInitialFeatures", False)
def track_points(self, width, height):
...
I am trying to learn about classes, can someone explain to me why this code is not working. I thought when calling a function from a class, "self" is automatically ommitted, but the interpreter tells me that argument "a" is missing (he thinks self = 10).
#! coding=utf-8
class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
d = test.do
print(d(10))
Instantiate the class first:
d = test().do
print(d(10)) # prints 100
test.do is an unbound method, test().do is bound. The difference is explained in this thread: Class method differences in Python: bound, unbound and static.
You have to instantiate the class first:
d = test()
then you can call a method:
print(d.do(10))
if you want to use method statically you have to declare it in python
#! coding=utf-8
class test:
def __init__(self):
"do something here"
#staticmethod
def do(a):
return a**2
d = test.do
print(d(10)) #and that's work
Since you haven't instantiated the class (a fancy term for created) you can't be assigning methods to any random variable. Like already said, you must create the object first, whilst making sure the method you call is a part of the class you called or connected to the class in some way (such as creating another class and then communicating that class with the current class). So you should first type d=test() followed by d.do().
Also, remember that in your declaration of the method you crated a parameter so what you done was wrong in itself anyway, because when you declared the do function, you should have put within the brackets the number you wanted to send to the method to calculate its square. So you type test.do(10) and then the 10 is sent by the self reference to the method to be done whatever it is you told it to do.
One more thing: although it isn't a huge deal, it helps if all of your class names begin with a capital letter, as this is usually the 'pythonic' way to do things, and it also makes your code much easier to read, because when you first called the class, somebody could easily mistaken it for an ordinary function
class test:
def __init__(self):
"do something here"
def do(self,a):
return a**2
def __call__(self,a):
return self.do(a)
a = test
test.do(a,10)
#or
a = test().do
a(10)
#or
a = test()
test.do(a,10)
#or
a = test()
print(a(10))