overloading __init__ of unittest.testcase - python

I want to add two variables to my subclass which is inherited from unittest.testcase
like I have:
import unittest
class mrp_repair_test_case(unittest.TestCase):
def __init__(self, a=None, b=None, methodName=['runTest']):
unittest.TestCase.__init__(self)
self.a= a
self.b = b
def test1(self):
..........
.......
def runtest()
mrp_repair_test_case(a=10,b=20)
suite = unittest.TestLoader().loadTestsFromTestCase(mrp_repair_test_case)
res = unittest.TextTestRunner(stream=out,verbosity=2).run(suite)
how can I acvhieve this:
I am getting this error:
ValueError: no such test method in ****<class 'mrp_repair.unit_test.test.mrp_repair_test_case'>:**** runTest
thanks

At first glance, it looks like you need to create an instance of mrp_repair_test_case. Your current line:
mrp_repair_test_case(a=10,b=20)
doesn't actually do anything.
Try (not tested):
def runtest():
m = mrp_repair_test_case(a=10, b=20)
suite = unittest.TestLoader().loadsTestsFromTestCase(m)
res = unittest.TextTestRunner(stream=out, verbosity=2).run(suite)
This assumes you've set up 'out' as a stream already.
Edit:
By the way, is there any reason you're not using a setUp method to set these values? That would be normal best practice. Looking at the documentation of loadTestsFromTestCase it looks like it will only accept the Class itself not an instance of it, which would mean you're rather working against the design of the unittest module.
Edit 2:
In response to your further information, I would actually set your uid and cursor values seperately at module level before calling the tests. I'm not a huge fan of globals normally, but if I'm understanding you correctly these values will be A) read-only B) always the same for the same customer which avoids most of the normal pitfalls in using them.
Edit 3:
To answer your edit, if you really want to use __init__ you probably can, but you will have to roll your own loadsTestsFromTestCase alternative, and possibly your own TestSuite (you'll have to check the internals of how it works). As I said above, you'll be working against the existing design of the module - to the extent that if you decide to do your testing that way it might be easier to roll your own solution completely from scratch than use unittest. Amend: just checked, you'd definately have to roll your own version of TestSuite, as the existing one creates a new instance of the TestCaseClass for each test.

Related

How to mock properly classes and methods from imported modules

I'm trying to create some unitary tests for a method that needs to instantiate some objects using classes from external modules that I don't want to use, as they need arguments that I can't pass at object initialization.
For example, imagine that the code I want to test has the following structure:
from module_one import Class_1
from module_two import Class_2
class MyMainClass()
def method_to_be_tested(self, stuff):
var_one = Class_1(stuff.data)
self.var_two = Class_2(var_one.data)
print("The var is %s" % self.var_two.attribute)
stuff is a complex argument, with several attributes that I can't mock.
This is what I have tried in my test method, using patch from unittest.mock (but it didn't work):
#patch('module_two.Class_2')
#patch('module_one.Class_1')
def test_method(self, mocked_class1, mocked_class2):
stuff = mock()
mocked_class1.return_value = 'some_stuff_that_i_dont_want'
mock_class2 = mock()
mock_class2.attribute = 'what_i_want_to_get'
mocked_class2 = mock_class2
mymainclass.method_to_be_tested(stuff)
assertEqual('what_i_want_to_get', mymainclass.var_two.attribute)
It seems that the patch or something isn't working, as it throws an error telling me that str object has no attribute data, referring to var_one when var_one.data is used as an argument for Class2.
What I want is to pass any argument to Class2 and get always what I defined in mock_class2.
Edit: mock() is imported from mockito module, but maybe I don't need this to achieve what I need.
You can certainly do that without mockito. Assuming that MyMainClass is defined in module mainmodule:
import unittest.mock as mock
class TestMyMainClass(unittest.TestCase):
#mock.patch('mainmodule.Class_2')
#mock.patch('mainmodule.Class_1')
def test_method(self, mocked_class1, mocked_class2):
stuff = mock.Mock()
mocked_class2_instance = mock.Mock()
mocked_class2_instance.attribute = 'what_i_want_to_get'
mocked_class2.return_value = mocked_class2_instance
mymainclass = MyMainClass()
mymainclass.method_to_be_tested(stuff)
self.assertEqual('what_i_want_to_get', mymainclass.var_two.attribute)
if __name__ == '__main__':
unittest.main()
Now if you think this test sucks, I have to agree.
You have to patch Class_1, yet it doesn't even appear in the test.
It is not obvious why Class_2 is relevant at all unless you are familiar with the internal implementation details of the method under test. Actually you are testing implementation details instead of (or in addition to) observable behavior, which is usually bad.
The behavior of the method depends (hopefully) on stuff.data but the test ignores that and will happily pass whatever it is. An yet you need a stuff object with a data attribute even if you don't care about what it is.
The main problem here is that by instantiating Class_1 and Class_2 inside the method you are tightly coupling the three pieces of code but now you want to test them in isolation. That's going to be hard and will probably lead to fragile and hard to read tests.
If you really want your code to be like that I suggest you test the method without mocking neither Class_1 nor Class_2. Now if you say you don't want to do that because stuff (or better, stuff.data; why are you passing the whole think when you only need the data?) is hard to mock or instantiate, I would guess that there is a problem with your design, but that is as far as I can get from your contrived example.

Calling functions / class methods inside a for loop

I'm working on a some classes, and for the testing process it would be very useful to be able to run the class methods in a for loop. I'm adding methods and changing their names, and I want this to automatically change in the file where I run the class for testing.
I use the function below to get a list of the methods I need to run automatically (there are some other conditional statements I deleted for the example to make sure that I only run certain methods that require testing and which only have self as an argument)
def get_class_methods(class_to_get_methods_from):
import inspect
methods = []
for name, type in (inspect.getmembers(class_to_get_methods_from)):
if 'method' in str(type) and str(name).startswith('_') == False:
methods.append(name)
return methods
Is it possible to use the returned list 'methods' to run the class methods in a for loop?
Or is there any other way to make sure i can run my class methods in my testingrunning file without having to alter or add things i changed in the class?
Thanks!
Looks like you want getattr(object, name[, default]):
class Foo(object):
def bar(self):
print("bar({})".format(self))
f = Foo()
method = getattr(f, "bar")
method()
As a side note : I'm not sure that dynamically generating lists of methods to test is such a good idea (looks rather like an antipattern to me) - now it's hard to tell without the whole project's context so take this remarks with the required grain of salt ;)

How to mock a singleton class method

Suppose we have the following structure:
class A():
class __A():
def __to_be_mocked(self):
#something here
def __init__(self):
with A.lock:
if not A.instance:
A.instance = A.__A()
def __getattr__(self,name):
return getattr(self.instance,name)
Now we want to mock the function __to_be_mocked.How can we mock it as the target accepted by mock.patch.object is package.module.ClassName.I have tried all methods like
target = A.__A
target = A.___A
and many more.
EDIT:
I solved it using
target=A._A__A and attribute as '_A__to_be_mocked`
Now the question is __to_be_mocked is inside __A so shouldn't it be ___A__to_be_mocked .
Is it because of setattribute in A or __init__ in A?
I mocked a lot of things in python and after did it lot of times I can say:
NEVER mock/patch __something attributes (AKA private attributes)
AVOID to mock/patch _something attributes (AKA protected attributes)
Private
If you mock private things you'll tangled production and test code. When you do this kind of mocks there is always a way to obtain the same behavior by patching or mocking public or protected stuffs.
To explain better what I mean by tangling production and test code I can use your example: to patch A.__B.__to_be_mocked() (I replaced __A inner class by __B to make it more clear) you need to write something like
patch('amodule.A._A__B._B__to_be_mocked')
Now by patching __to_be_mocked you are spreading A, B and to_be_mocked names in your test: that is exactly what I mean to tangled code. So if you need to change some name you should go in all your test and change your patches and no refactoring tool can propose to you to change _A__B._B string.
Now if you are a good guy and take your tests clean you can have just a few points where these names come out but if it is a singleton I can bet that it will spot out like mushrooms.
I would like to point out that private and protected have nothing to do with some security concern but are just way to make your code more clear. That point is crystal clear in python where you don't need to be a hacker to change private or protected attributes: these conventions are here just to help you on reading code where you can say Oh great! I don't need to understand what is it ... it just the dirty work. IMHO private attributes in python fails this goal (__ is too long and see it really bother me) and protected are just enough.
Side note: little example to understand python's private naming:
>>> class A():
... class __B():
... def __c(self):
... pass
...
>>> a = A()
>>> dir(a)
['_A__B', '__doc__', '__module__']
>>> dir(a._A__B)
['_B__c', '__doc__', '__module__']
To come back at your case: How your code use __to_be_mocked() method? is it possible to have the same effect by patch/mock something else in A (and not A.__A) class?
Finally, if you are mocking private method to sense something to test you are in the wrong place: never test the dirty work it should/may/can change without change your tests. What you need is to test code behavior and not how it is written.
Protected
If you need test, patch or mock protected stuffs maybe your class hide some collaborators: test it and use your test to refactor your code then clean your tests.
Disclaimer
Indeed: I spread this kind of crap in my tests and then I fight to remove it when I understand that I can do it better.
Class & instance members starting with double underscores have their names rewritten to prevent collisions with same-name members in parent classes, making them behave as if "private". So __B here is actually accessible as A._A__B. (Underscore, class name, double underscored member name). Note that if you use the single-underscore convention (_B), no rewriting happens.
That being said, you'll rarely see anyone actually use this form of access and especially not in prod code as things are made "private" for a reason. For mocking, maybe, if there's no better way.

Python dependency injection

I have 3 modules: A, B, C
A contains a set of classes that B has fetchers for.
B contains a bunch of singletons that just deal with caching created objects and providing them when requested. Essentially just fetchers.
C is a list of functions that requires instances of A.
The operation that I need to do is something along the lines of:
C::SomeFunc():
B.getInstance("instance ID")
B::getInstance(someID: str) -> A:
-look at cache, which is either [] or {}
-if it is in cache, return that, else do: A(someID)
My question is, how would you pass around the instances of these modules around? This question is primarily motivated by my lack of understanding of Python's memory allocation system.
I could do something along the lines of constructor-based dependency injection to get an instance of A,B,C where they need to go, and then have some "master/god/controller" object that just passes things where they need to go -
eg:
class god(object):
def __init__(self):
a = A()
b = B()
c = C(b)
.....
.....
class C(object):
def __init__(self, B_instance):
self.B = B_instance
def SomeFunc(self, instanceID):
self.B.getInstance(instanceID)
but this seems like a hack.
Any suggestions?
Thanks!
I've seen some packages that offer an instance provider on there on PyPI if that's what you are looking for. Personally, I didn't want to deal with another object to obtain instances. So I created my own library for this (Python 3 only). You only need #inject and annotations.
from py3njection import inject
from some_package import ClassToInject
class Demo:
#inject
def __init__(self, object_to_use: ClassToInject):
self.dependency = object_to_use
demo = Demo()
You can find it here.
It basically makes a new instance each time the method is called.
Testing is easy with this since you only have to pass mocks as arguments to unittest your function/method.
I've added #singleton too.
If you need even more instantiation ways, like the cache system you're describing, the docs explain how to easily implement your own. Everything cache related would be taken care of in a factory, and the objects that depends on them wouldn't have to know how to get them.
But if you're on Python 2 or if you need to have more control on injections, this could work too. But you still have to manipulate a provider.
I recently released a small library that might help you achieve this. Feedback is very welcome :D
https://github.com/suned/serum
You can use injectable for that. It's a dependency injection autowiring micro-framework.
This is what your code would look like:
#injectable(singleton=True)
class MySingleton:
...
#autowired
def func_that_needs_my_singleton(my_singleton: Autowired(MySingleton)):
...

What's the right way of unit-testing a python class?

I'm not sure what's the best way to build independent unit tests on methods of a python class. Here is a trivial example:
class MyClass(object):
def __init__(self, data):
self.data = data
def myMethod(self):
#do something
return True
I'm building unit tests like this:
class TestMyClass(unittest.TestCase):
def test_init(self):
mydata = mock.Mock()
c = MyClass(mydata)
self.assertEqual(c.data, mydata)
def test_myMethod(self):
mydata = mock.Mock()
c = MyClass(mydata)
self.assertTrue(c.myMethod())
OK, this is very trivial... but the point is: test_myMethod() depends on __init__ because I have to instantiate the object itself: it isn't really isolated. The only way that has come to my mind to solve this issue is mocking the object itself... but how can I test a real method on a mocked object?
I know that in real world a perfect isolation could be impossible, but I'm curious to know if there are better ways.
It comes down to what you want to test and in how much granularity. For example, what exactly is the assertion that c.data equals the data you have just assigned in the previous line actually test? It tests a single line of practical code, and it tests a rather unimportant implementation detail. This is probably much too granular to bother.
You want to ensure that your object behaves as it should overall. That means you want to test that you can instantiate it, and then assert that
if you instantiate it with data A and then call method B the result will be C
if you instantiate it with data D and then call method B the result will be E
if you try to instantiate it with incorrect data that an error is thrown
Your tests should focus on object behaviour, not on testing implementation minutiae. Write your tests so you could drop in an alternative object implementing the same behaviour in a different way without breaking your tests. You are writing that class to get some specified tasks done; test that your implementation can get those tasks done, not how it gets them done.
Exempli gratia:
def test_worksWithDataA(self):
c = MyClass({'some': 'data'})
self.assertTrue(c.myMethod())
def test_worksWithDataB(self):
c = MyClass({'other': 'data'})
self.assertFalse(c.myMethod())
def test_rejectsDataC(self):
with self.assertRaises(SomeException):
MyClass(None)
You only need to mock something if you need to pass a dependency, but that dependency is too complex to instantiate for the sake of the test. As long as your data is just a dict, there's no need to mock it. If your data is a complex type on its own, then you may want to mock it in order to test MyClass, without getting tangled up in having to test that other class at the same time. When mocking, again, mock the expected behaviour of that class; as a rule of thumb, all the behaviour you're asserting your class has using unit tests can be mocked elsewhere.

Categories