-1

I am trying to write a unit test for a code, in which there is a method which is called whenever an exception is raised. Now this method is called by multiple exceptions. My main aim is to write down a unit test for which I am able to assert whether the said exception is the trigger for that method.

For example: (generic method divide)

try:
    divide(2,0)
except ZeroDivisionError:
    method_to_be_called()

Now in my test case, i want to test whether the triggering exception for method_to_be_called() is ZeroDivisionError Any ideas on how I can accomplish that?

Gaurav Sood
  • 157
  • 3
  • 16
  • Is `method_to_be_called()` part of your application, or part of your test suite? If the latter, just pass the exception to it. – Sven Marnach Mar 30 '12 at 13:16
  • method_to_be_called() is part of the application. It is called whenever the ZeroDivisionError occurs – Gaurav Sood Mar 30 '12 at 13:19
  • Then I really don't get what you are doing here. So the code sample you gave is application code, not test suite code, right? And you want to test from the outside what happens somewhere deep inside the application code? I think you have to explain a lot more about the context, and in particular *why* you want to do all this. – Sven Marnach Mar 30 '12 at 13:28
  • i have not written the test case here. the code above is just an example of what i wish to achieve. the test case is different code which will try something like this: assertEqual(calling-exception-of- method_to_be_called,ZeroDivisionError) I have to implement the test case as the method_to_be_called() is called by multiple exceptions, but by only one at a time. so in testing, its imperative that the calling exception is determined. – Gaurav Sood Mar 30 '12 at 13:39
  • Perhaps take a look at http://stackoverflow.com/questions/1278705/python-when-i-catch-an-exception-how-do-i-get-the-type-file-and-line-number ? – Lee Netherton Mar 30 '12 at 13:52
  • @GauravSood: Sorry for all my questions, but we somehow got stuck in an infinite communication loop. :) As I understand things now, the test suite calls some application code, which internally calls `method_to_be_called()` at some point, triggered by an exception handler. And now your test suite is supposed to figure out what exception has triggered `method_to_be_called()` after all these functions return? You can certainly replace `method_to_be_called()` by a mocked version that keeps record of the exception an check it after the application code has returned… – Sven Marnach Mar 30 '12 at 13:59
  • Since there is no effect visible from the outside of the exception that triggered `method_to_be_called()`, your test suite *shouldn't* test this. It does not change the behaviour of your application in any way, so it is pointless to test it. When I asked for a rationale, I actuallay would have like to know *why* `method_to_be_called()` exists in the first place, why it is called in many places and in particular why you think it is useful to test which exception triggered that this function is called. – Sven Marnach Mar 30 '12 at 14:01
  • Sven: yes. the test case is supposed to assert which exception called method_to_be_called() . I still did not get how to check it... – Gaurav Sood Mar 30 '12 at 14:08
  • @GauravSood: The answer to your question is probably "design your code in a different way" or "don't test this at all", but I cannot tell you which one it is without further information. – Sven Marnach Mar 30 '12 at 14:11
  • "If the implementation is hard to explain, it's a bad idea." -- Zen of Python – KurzedMetal Mar 30 '12 at 15:23

2 Answers2

1

Maybe sys.exc_info() will be helpful?

Tupteq
  • 2,986
  • 1
  • 21
  • 30
  • This would have to be checked inside `method_to_be_called()`. If we want to touch that code, it would be a lot better to pass the exception object to that function instead of recovering it inside of the function. – Sven Marnach Mar 30 '12 at 13:30
  • from sys.exc_info() or using the traceback module, i was able to extract the information about the raised exception. but how will i assert that the method_to_be_called() was called by the said exception (in this case, ZeroDivisionError) – Gaurav Sood Mar 30 '12 at 13:32
  • @Sven : i need to write a test case for the job, as the method will be called by a multitude of exceptions. so i need to assert which exception has called the method. – Gaurav Sood Mar 30 '12 at 13:34
  • @GauravSood: Without more information on the context, and in particular a rationale *why* you want to do this, I don't think I can help you in a meaningful way. – Sven Marnach Mar 30 '12 at 13:37
  • @Gustav: What do you mean, the method "was called"? This is a question you can only ask while `method_to_be_called` is running, that is, *the question* only makes sense inside the method itself. Are you maybe trying to make sure that _if the exception occurs, the method will be called?_ – alexis Mar 30 '12 at 14:16
  • i was thinking of this: try: divide(2,0) except ZeroDivisionError: raise exception_defined_by_me[code] in exception_defined_by_me, i would call the method_to_be_called. In the test case, i would just need to check: assertRaises(exception_defined_by_me,divide,2,0) there are a few tracebacks i am getting in this code though – Gaurav Sood Mar 30 '12 at 14:21
  • Oh, I see. In that case, **DON'T DO THAT!**. It's fine to define your own exceptions, but you should only use them as containers for context information you want to pass back. Do **NOT** call the error handler method inside the exception's constructor. Call it from the `try ... except` block at whatever place you catch the exception. – alexis Mar 30 '12 at 14:33
  • Unless it's not an error handler but an exception logger. That's a different matter. Clear this up please so we can comment usefully. – alexis Mar 30 '12 at 14:38
  • ok. won't do that in that case. but am dreadfully stuck on the problem of writing the test case... – Gaurav Sood Mar 30 '12 at 14:44
  • Well, what *do* you need to test for? Is the method just a logger, or does it repair something or other? – alexis Mar 30 '12 at 14:47
  • the method performs a few operations like sending an email notifying about the traceback. – Gaurav Sood Mar 30 '12 at 14:56
0

It seems you are (or should be) trying to check whether your method will be called whenever one of the exceptions occurs. In that case your approach is mistaken: Your unit test should not be asking which exception happened. It should be raising each of the exceptions you're interested in, and checking whether the method was called. (So, don't use assertRaises: That doesn't raise an exception, it expects its argument to do so).

How to check this? NOT by trying to look inside the method. If the purpose of your method is to do something like write to a log when an exception occurs, raise the exception and then check if the log entry was correctly made.

If your method's actions ("side-effects") are difficult to detect in a test, you should replace it with a "mock" method: That's a method that takes the place of the real thing, but its job is to help the testing framework ensure it was called properly. Look it up in your testing framework.

alexis
  • 48,685
  • 16
  • 101
  • 161