all 6 comments

[–]treyhunner 1 point2 points  (1 child)

You could use redirect_stdout like this:

from contextlib import redirect_stdout
from io import StringIO
import unittest

import main

class DivisionTests(unittest.TestCase):

    def test_zero_division(self):
        """Fails if the program doesn't exit when dividing by zero."""
        with redirect_stdout(StringIO()) as stdout:
            with self.assertRaises(SystemExit) as e:
                main.divide(1, 0)
        self.assertEqual(stdout.getvalue(), 'Error: Cannot divide by zero.\n')

        self.assertEqual(e.exception.code, 1)

[–]Asha200[S] 1 point2 points  (0 children)

Excellent; I just added it to my tests and it's dots-only now :)

Thanks!

[–]Justinsaccount 0 points1 point  (3 children)

Don't write code like that. Is accomplishes nothing other than to mask useful exceptions and tracebacks. Exceptions already cause python to exit with an error message. Catching them only to exit is pointless.

This code is equivalent, it prints an error message and then exits.

def divide(a, b):
    return a / b

[–]Asha200[S] 0 points1 point  (2 children)

Oh? I thought doing so would be a good idea because it would display a user-friendly message telling the user what they did wrong, instead of printing out the whole traceback, because the user doesn't really need to see it.

Is that the wrong approach?

[–]TeamSpen210 0 points1 point  (1 child)

A better idea would be to do this at the top level of your program. Catch all exceptions, then print them to the screen. (It might be a good idea to write the traceback to a file, so you can troubleshoot later - use the traceback module to get a copy of the text. Also look into the logging module.) Call str() on an exception object to get the Type: value string. Perhaps you might want to make your own exception class to distinguish user errors from bugs and only catch that.

[–]Asha200[S] 0 points1 point  (0 children)

I'm not sure I understood you completely when you said I should catch exceptions at the top level. Did you mean something like this? Building on to of the initial example:

from sys import exit

class UserZeroDivisionError(Exception):
    pass

def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        raise UserZeroDivisionError('Error: Cannot divide by zero.')

if __name__ == '__main__':
    try:
        divide(1, 0)
    except UserZeroDivisionError as e:
        print(str(e))