I am using the skip decorator for a test:
#skip('I want this to skip')
def test_abc(self):
I also have a nose plugin to report test results with a defined
def beforeTest(self, *args, **kwargs):
the test case test_abc is getting captured by the beforeTest method. How can I check for the decorator value in my beforeTest method?
I see that the definition of unittest decorator has the following code:
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
But I dont know how to access it from beforeTest.
When running args[0].test has the test case object but I can seem to find where __unittest_skip__ is defined
Thanks!
Looking at the source code, there doesn't seem to be a clean way to do this. TestCase seems to know what method it is testing based on the _testMethodName implementation detail. If you have a reference to the running test case (maybe args[0].test? I'm not familiar with nose...) you could use that, or you could parse it out of the return value from TestCase.id(). Assuming you aren't doing something really funky, it would be something like:
test_name = test_case.id().rsplit('.', 1)[-1]
test_method = getattr(test_case, test_name)
if getattr(test_method, '__unittest_skip__', False):
# Method skipped. Don't do normal stuff.
Related
I am adding some tests to existing not so test friendly code, as title suggest, I need to test if the complex method actually calls another method, eg.
class SomeView(...):
def verify_permission(self, ...):
# some logic to verify permission
...
def get(self, ...):
# some codes here I am not interested in this test case
...
if some condition:
self.verify_permission(...)
# some other codes here I am not interested in this test case
...
I need to write some test cases to verify self.verify_permission is called when condition is met.
Do I need to mock all the way to the point of where self.verify_permission is executed? Or I need to refactor the def get() function to abstract out the code to become more test friendly?
There are a number of points made in the comments that I strongly disagree with, but to your actual question first.
This is a very common scenario. The suggested approach with the standard library's unittest package is to utilize the Mock.assert_called... methods.
I added some fake logic to your example code, just so that we can actually test it.
code.py
class SomeView:
def verify_permission(self, arg: str) -> None:
# some logic to verify permission
print(self, f"verify_permission({arg=}=")
def get(self, arg: int) -> int:
# some codes here I am not interested in this test case
...
some_condition = True if arg % 2 == 0 else False
...
if some_condition:
self.verify_permission(str(arg))
# some other codes here I am not interested in this test case
...
return arg * 2
test.py
from unittest import TestCase
from unittest.mock import MagicMock, patch
from . import code
class SomeViewTestCase(TestCase):
def test_verify_permission(self) -> None:
...
#patch.object(code.SomeView, "verify_permission")
def test_get(self, mock_verify_permission: MagicMock) -> None:
obj = code.SomeView()
# Odd `arg`:
arg, expected_output = 3, 6
output = obj.get(arg)
self.assertEqual(expected_output, output)
mock_verify_permission.assert_not_called()
# Even `arg`:
arg, expected_output = 2, 4
output = obj.get(arg)
self.assertEqual(expected_output, output)
mock_verify_permission.assert_called_once_with(str(arg))
You use a patch variant as a decorator to inject a MagicMock instance to replace the actual verify_permission method for the duration of the entire test method. In this example that method has no return value, just a side effect (the print). Thus, we just need to check if it was called under the correct conditions.
In the example, the condition depends directly on the arg passed to get, but this will obviously be different in your actual use case. But this can always be adapted. Since the fake example of get has exactly two branches, the test method calls it twice to traverse both of them.
When doing unit tests, you should always isolate the unit (i.e. function) under testing from all your other functions. That means, if your get method calls other methods of SomeView or any other functions you wrote yourself, those should be mocked out during test_get.
You want your test of get to be completely agnostic to the logic inside verify_permission or any other of your functions used inside get. Those are tested separately. You assume they work "as advertised" for the duration of test_get and by replacing them with Mock instances you control exactly how they behave in relation to get.
Note that the point about mocking out "network requests" and the like is completely unrelated. That is an entirely different but equally valid use of mocking.
Basically, you 1.) always mock your own functions and 2.) usually mock external/built-in functions with side effects (like e.g. network or disk I/O). That is it.
Also, writing tests for existing code absolutely has value. Of course it is better to write tests alongside your code. But sometimes you are just put in charge of maintaining a bunch of existing code that has no tests. If you want/can/are allowed to, you can refactor the existing code and write your tests in sync with that. But if not, it is still better to add tests retroactively than to have no tests at all for that code.
And if you write your unit tests properly, they still do their job, if you or someone else later decides to change something about the code. If the change breaks your tests, you'll notice.
As for the exception hack to interrupt the tested method early... Sure, if you want. It's lazy and calls into question the whole point of writing tests, but you do you.
No, seriously, that is a horrible approach. Why on earth would you test just part of a function? If you are already writing a test for it, you may as well cover it to the end. And if it is so complex that it has dozens of branches and/or calls 10 or 20 other custom functions, then yes, you should definitely refactor it.
So i have a python class say
class Nested(object):
def method_test(self):
#do_something
The above class is being maintained by some other group so i can't change it. Hence we have a wrapper around it such that
class NestedWrapper(object):
self.nested = Nested()
def call_nested(object):
self.nested.method_test()
Now, I am writing test cases to test my NestedWrapper. How can i test that in one of my test, the underlying method of Nested.method_test is being called? Is it even possible?
I am using python Mock for testing.
UPDATE I guess I was implicitly implying that I want to do Unit Testing not a one off testing. Since most of the responses are suggesting me to use debugger, I just want to point out that I want it to be unit tested.
I think you can just mock Nested.method_test and make sure it was called...
with mock.patch.object(Nested, 'method_test') as method_test_mock:
nw = NestedWrapper()
nw.call_nested()
method_test_mock.called # Should be `True`
If using unittest, you could do something like self.assertTrue(method_test_mock.called), or you could make a more detailed assertion by calling one of the more specific assertions on Mock objects.
I've already browsed through the mock documentations, and i've seen some examples where mock has been used. But, being a newbie, i find it hard to use mock in my tests.
test_scoring.py - I am creating a test to make sure that a function DOES NOT get called whenever i create an item.
The function compute_score() that i'd like to mock is part of a class HistoryItem.
What i got so far is this :
#test_scoring.py
#mock.patch('monitor.report.history_item.HistoryItem.compute_score')
def test_save_device_report(self):
....
result = factory.create_history_item(jsn)
# If the mocked method gets called after the above function is used, then there should be an error.
So, how do I mock the method? I'm quite confused on how to use it, because there are different ways in the resources i found.
I'd really appreciate your help.
When using the patch method as a decorator, you need to specify a second parameter to your test function:
#mock.patch('monitor.report.history_item.HistoryItem.compute_score')
def test_save_device_report(self, my_mock_compute_score):
....
# Assuming the compute_score method will return an integer
my_mock_compute_score.return_value = 10
result = factory.create_history_item(jsn)
# Then simulate the call.
score = result.compute_score() # This call could not be necessary if the previous
# call (create_history_item) make this call for you.
# Assert method was called once
my_mock_compute_score.assert_called_once()
# Also you can assert that score is equal to 10
self.assertEqual(score, 10)
Note that the mocks should be used only when you've tested the patched method or object in another test.
Where to patch? -> https://docs.python.org/3/library/unittest.mock.html#where-to-patch
Edit
This patch is gonna to avoid a real call to compute_score(). However, after reread your post I can see you want to assert your function doesn't get called.
Hopefully, the called attribute is present in every mock you make, so for that you can use:
#mock.patch('monitor.report.history_item.HistoryItem.compute_score')
def test_save_device_report(self, my_mock_compute_score):
...
result = factory.create_history_item(jsn)
self.assertFalse(my_mock_compute_score.called)
...
I made a command in django which calls a function.
That function does a django orm call:
def get_notes():
notes = Note.objects.filter(number=2, new=1)
return [x.note for x in notes]
I want to patch the actual lookup:
#mock.patch('Note.objects.filter', autospec=True)
def test_get_all_notes(self, notes_mock):
get_notes()
notes_mock.assert_called_once_with(number=2, new=1)
I get the following assertion error:
AssertionError: Expected call: filter(number=2, new=1)
Actual call: filter(number=2, new=1)
I search on google and stackoverflow for hours, but I still haven't a clue.
Can anyone point me in the right direction, I think it might be an obvious mistake I'm making...
AFAIK you can't use patch() like this. Patch target should be a string in the form package.module.ClassName. I don't know much about django but I suppose Note is a class so Note.objects.filter is not something you can import and hence use in patch(). Also I don't think patch() can handle attributes. Actually I don't quite understand why the patch works at all.
Try using patch.object() which is specifically designed to patch class attributes. It implies Note is already imported in your test module.
#mock.patch.object(Note, 'objects')
def test_get_all_notes(self, objects_mock):
get_notes()
objects_mock.filter.assert_called_once_with(number=2, new=1)
I've removed autospec because I'm not sure it will work correctly in this case. You can try putting it back if it works.
Another option might be to use patch() on whatever you get with type(Note.objects) (probably some django class).
As I've said I don't know much about django so I'm not sure if these things work.
In general I want to disable as little code as possible, and I want it to be explicit: I don't want the code being tested to decide whether it's a test or not, I want the test to tell that code "hey, BTW, I'm running a unit test, can you please not make your call to solr, instead can you please stick what you would send to solr in this spot so I can check it". I have my ideas but I don't like any of them, I am hoping that there's a good pythonic way to do this.
You can use Mock objects to intercept the method calls that you do not want to execute.
E.g. You have some class A, where you don't want method no() to be called during a test.
class A:
def do(self):
print('do')
def no(self):
print('no')
A mock object could inherit from A and override no() to do nothing.
class MockA(A):
def no(self):
pass
You would then create MockA objects instead of As in your test code. Another way to do mocking would be to have A and MockA implement a common interface say InterfaceA.
There are tons of mocking frameworks available. See StackOverflow: Python mocking frameworks.
In particular see: Google's Python mocking framework.
Use Michael Foord's Mock
in your unit test do this:
from mock import Mock
class Person(object):
def __init__(self, name):
super(Person, self).__init__()
self.name = name
def say(self, str):
print "%s says \"%s\"" % (self.name, str)
...
#In your unit test....
#create the class as normal
person = Person("Bob")
#now mock all of person's methods/attributes
person = Mock(spec=person)
#talkto is some function you are testing
talkTo(person)
#make sure the Person class's say method was called
self.assertTrue(person.say.called, "Person wasn't asked to talk")
#make sure the person said "Hello"
args = ("Hello")
keywargs = {}
self.assertEquals(person.say.call_args, (args, keywargs), "Person did not say hello")
The big problem that I was having was with the mechanics of the dependency injection. I have now figured that part out.
I need to import the module in the exact same way in both places to successfully inject the new code. For example, if I have the following code that I want to disable:
from foo_service.foo import solr
solr.add(spam)
I can't seem to do this in the in my test runner:
from foo import solr
solr = mock_object
The python interpreter must be treating the modules foo_service.foo and foo as different entries. I changed from foo import solr to the more explicit from foo_service.foo import solr and my mock object was successfully injected.
Typically when something like this arises you use Monkey Patching (also called Duck Punching) to achieve the desired results. Check out this link to learn more about Monkey Patching.
In this case, for example, you would overwrite solr to just print the output you are looking for.
You have two ways to do this is no ,or minimal in the case of DI, modifications to your source code
Dependency injection
Monkey patching
The cleanest way is using dependency injection, but I don't really like extensive monkeypatching, and there are some things that are non-possible/difficult to do that dependency injection makes easy.
I know it's the typical use case for mock objects, but that's also an old argument... are Mock objects necessary at all or are they evil ?
I'm on the side of those who believe mocks are evil and would try to avoid changing tested code at all. I even believe such need to modify tested code is a code smell...
If you wish to change or intercept an internal function call for testing purpose you could also make this function an explicit external dependency set at instanciation time that would be provided both by your production code and test code. If you do that the problem disappear and you end up with a cleaner interface.
Note that doing that there is not need to change the tested code at all neither internally nor by the test being performed.