pytest : classmethods and boundmethods - python

So I'm using pytest and everything works ok, but something bothers me. When I put some method in my TestClass definition, it's y default a bound method, but I never actually get to use "self".
Now, the "setup_class" (or teardown_class) methods are necessarily classmethods, hence I cannot call my bound methods from setup_class.
So do I define every method as classmethods and get along with it, or am I missing something ? Should I simply never use bound methods ?
class TestSomething(object):
#classmethod
def setup_class(cls):
"do something"
cls.bound_method(?) #how do I call it ?
def bound_method(self):
"do something I'd like to do in setup_class"

You can use method setup and teardown methods in a class
def setup_method(self, method):
""" setup any state tied to the execution of the given method in a
class. setup_method is invoked for every test method of a class.
"""
def teardown_method(self, method):
""" teardown any state that was previously setup with a setup_method
call.
"""
That runs on every test method (bound test function) defined in the class

Related

unittesting a function in different file in python

I'm trying to test an add function that excites in calc.py
import unittest
import calc
class TestCalc(unittest.TestCase):
def test_add(self):
result = calc.add(10,5)
self.assertEqual(result,15)
My question is what does self means in this example
I know that self is an instance of a class.But, can you give me an example of what the value of self would be in my example.
self is a reference to the instance of TestCalc that is instantiated by the test runner from unittest when you run your tests.
More generally, when an object is instantiated and one of its methods is called (such as test_add(), called by unittest's test runner in your case), self is used to refer to the instance the method is called on, allowing access to its other properties and methods (such as assertEqual(), inherited from unittest.TestCase, in your case).

How to use setup_class to define a variable to be accessed in all methods of class

I need to define a variable in a fixture method setup_class for pytest like
class testClassForPytest:
#classmethod
def setup_class(cls):
m = aClassInstance(classInput)
def test_case_1(self):
#use of the instance m with a method of its class
I tried above approach but wasn't able to use the instance m.
It seems like the setting up of test suite (the class) for pytest is inherited from the standard python library unittest. With that library, the method is called setUpClass and should probably call the same method on its parent class. However since you are using pytest, which doesn't seem to follow the idea of test suites, I'm not entirely sure this is a problem. Still, it might be one source of problems if the method is supposed to be called something else.
In your code the method setup_class, you set a variable m to a value, but this variable is restricted to the local scope of the method. Only if you previously defined the variable on the scope of the class, or if you explicitly reference the variable in the class scope, can you later access the value again.
For example you could simply move the declaration into the class scope:
class testClassForPytest:
m = aClassInstance(classInput)
def test_case_1(self):
#use of the instance m with a method of its class
In this case you don't the setup method at all. If you need specific inputs that are not available on class declaration, you can also set the variable directly:
#classmethod
def setup_class(cls):
cls.m = aClassInstance(classInput)
I suppose that you meant, that in setup_class you meant to do cls.m = aClassInstance(classInput), not just m = ...
for that, you could modify your code to use pytest's class scope fixture to achieve the same result:
#pytest.fixture(scope='class')
def setup_class(request):
m = aClassInstance(classInput)
request.cls.m = m # makes pytest to add created instance to class to which fixture is applied to
#pytest.mark.usefixtures("setup_class")
class testClassForPytest:
def test_case_1(self):
#use of the instance m as self.m
class Test_visualization:
data: int = 0
#pytest.fixture(autouse=True)
def setup(self):
self.data = 3
#classmethod
def setup_class(cls):
Test_visualization.data = 3
setup_class Class will run only onces inside class
setup will run for every test creating a new instance of the class
From pytest documentation its written
Something to be aware of when grouping tests inside classes is that each test has a unique instance of the class. Having each test share the same class instance would be very detrimental to test isolation and would promote poor test practices
So it is better to define class variables that are common across all tests and instance variables that are created every time for a test
Example for Pytest auto use Fixture
Pytest Fixture Documentation

Why does a method within a class work even if not marked with #classmethod or #staticmethod?

I'm new to Python and just learning about its implementation of objects/classes. I understand the difference between an instance method, class method, and static method, I think, but what I don't understand is why a method that has not been decorated as a #classmethod or #staticmethod can be called from the class itself.
My very (very) basic example:
class TestClass:
def __init__(self):
pass
#staticmethod
def print_static_stuff(stuff):
print(stuff)
def print_stuff(stuff):
print(stuff)
TestClass.print_stuff("stuff") # prints "stuff"
TestClass.print_static_stuff("static stuff") # prints "static stuff"
The method print_stuff() seems to act as a static method when called on the class, taking the argument as it's single parameter and not the class (cls). Why can the method not decorated with #staticclass be called on the class? Is this by design or just a weird side-effect, and why? From what I've learned so far, Python, by design, has few to no "weird side-effects".
The first parameter being named self is merely a convention. The instance will be passed as the first positional argument independent of what you've named it (in this case you've called it stuff).

where should I define functions that i use in __init__

I'm writing a class that makes use of some functions inside its __init__ function and I'm not sure about the best practice of where to define those functions. I usually like to define __init__ first but if I need to use the a function/method within the __init__ then it needs to be defined first. I dont want to define it outside the class as its useless outside the class but it seems messy to me to define methods before the __init__. What are the normal conventions for this?
Just add the methods to your class like every other method
class Test(object):
def __init__(self):
self.hi()
def hi(self):
print "Hi!"
No problem at all.
While it is not mentioned in the Python Style Guide IIRC, it's convention to let __init__ be the first method in your class.
The normal convention is indeed to put __init__ before other methods. The reason this works is that functions aren't evaluated until invoked. From the Python docs:
A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object (a wrapper around the executable code for the function). This function object contains a reference to the current global namespace as the global namespace to be used when the function is called.
The function definition does not execute the function body; this gets executed only when the function is called.
It's better to define __init__ function as first function, and you can call functions defined after __init__ inside it.
class A:
def __init__(self):
print self.x()
def x(self):
return 10
Why should it be 'messy' to define methods after the init ? Think about it that way :
When you define
class MyClass(object):
def __init__(self):
self.something = whatever
self.do_something_else()
def do_something_else(self):
...
__init__ is a method of your MyClass class, just like do_something is; it's just the first method of the class that will be called when you create an instance of MyClass. So, putting __init__ first is not only customary but also logical.
Your do_something_else method doesn't have to be defined first because you use it in __init__. From the point of view of MyClass, it's a method like another. When you create your myclass=MyClass() instance, do_something_else has already been defined...

How to decorate an object method?

I need to decorate a object's method. It needs to be at runtime because the decorators applied on the object depends on the arguments that the user gave when calling the program (arguments supplied with argv), so a same object could be decorated 3 times, 2 times, or not be decorated at all.
Here is some context, the program is a puzzle solver, the main behavior is to find a solution for the puzzle automatically, by automatically I mean without user intervention. And here is where the decoration gets to play, one of the things I want to is draw a graph of what happened during the execution, but I want to do so only when the flag --draw-graph is used.
Here is what I've tried:
class GraphDecorator(object):
def __init__(self, wrappee):
self.wrappee = wrappee
def method(self):
# do my stuff here
self.wrappee.method()
# do more of stuff here
def __getattr__(self,attr):
return getattr(self.wrappee,attr)
And why it did NOT work:
It did not work because of the way I built the application, when a method that did not exist in my Decorator class was called it felt back to the implementation of the decorated class, the problem is that the application always started invoking the method run that did not need to be decorated, so the undecorated fall back was used and from inside the undecorated form it always called undecorated methods, what I needed was to replace the method from the object, not to proxy it:
# method responsible to replace the undecorated form by the decorated one
def graphDecorator(obj):
old_method = obj.method
def method(self):
# do my stuff here
old_method()
# do more of my stuff
setattr(obj,'method',method) # replace with the decorated form
And here is my problem, the decorated form does not receive self when it is called resulting on a TypeError because of the wrong number of arguments.
The problem was that I couldn't use func(self) as a method. The reason is that setattr() method does not bound the function, and the function acts like it a static method - not a class method -, thanks to the introspective nature of python I've able to come up with this solution:
def decorator(obj):
old_func = obj.func # can't call 'by name' because of recursion
def decorated_func(self):
# do my stuff here
old_func() # does not need pass obj
# do some othere stuff here
# here is the magic, this get the type of a 'normal method' of a class
method = type(obj.func)
# this bounds the method to the object, so self is passed by default
obj.func = method(decorated_func, obj)
I think this is the best way to decorate a object's method at runtime, though it would be nice to find a way to call method() directly, without the line method = type(obj.func)
You might want to use __getattribute__ instead of __getattr__ (the latter being only called if "standard" lookup fails):
class GraphDecorator(object):
def __init__(self, wrappee):
self.__wrappee = wrappee
def method(self):
# do my stuff here
self.wrappe.method()
# do more of stuff here
def __getattribute__(self, name):
try:
wrappee = object.__getattribute__(self, "_GraphDecorator__wrappee")
return getattr(wrappee, name)
except AttributeError:
return object.__getattribute__(self, name)
I need to decorate a object's method. It needs to be at runtime because the decorators applied on the object depends on the arguments that the user gave when calling the program (arguments supplied with argv), so a same object could be decorated 3 times, 2 times, or not be decorated at all.
The above is unfortunately incorrect, and what you are trying to do is unnecessary.
You can do this at runtime like so. Example:
import sys
args = sys.argv[1:]
class MyClass(object):
pass
if args[0]=='--decorateWithFoo':
MyClass = decoratorFoo(MyClass)
if args[1]=='--decorateWithBar'
MyClass = decoratorBar(MyClass)
The syntax:
#deco
define something
Is the same thing as:
define something
something = deco(something)
You could also make a decorator factory #makeDecorator(command_line_arguments)
"It needs to be at runtime because the decorators applied on the object depends on the arguments that the user gave when calling the program"
The don't use decorators. Decorators are only syntactical support for wrappers, you can just as well use normal function/method calls instead.

Categories

Resources