unittest: assertRaises() with an instance instead of a type

Steve Howell showell30 at yahoo.com
Thu Mar 29 07:50:44 CEST 2012

On Mar 28, 6:55 pm, Ben Finney <ben+pyt... at benfinney.id.au> wrote:
> Steven D'Aprano <steve+comp.lang.pyt... at pearwood.info> writes:
> > (By the way, I have to question the design of an exception with error
> > codes. That seems pretty poor design to me. Normally the exception *type*
> > acts as equivalent to an error code.)
> Have a look at Python's built-in OSError. The various errors from the
> operating system can only be distinguished by the numeric code the OS
> returns, so that's what to test on in one's unit tests.

To the extent that numeric error codes are poor design (see Steven's
comment) but part of the language (see Ben's comment), it may be
worthwhile to consider a pattern like below.

Let's say you have a function like save_config, where you know that
permissions might be an issue on some systems, but you don't want to
take any action (leave that to the callers).  In those cases, it might
be worthwhile to test for the specific error code (13), but then
translate it to a more domain-specific exception.  This way, all your
callers can trap for a much more specific exception than OSError.
Writing the test code for save_config still presents some of the
issues that the OP alluded to, but then other parts of the system can
be tested with simple assertRaises().

  import os

  class ConfigPermissionError:

  def save_config(config):
      dir = os.mkdir('/config')
    except OSError, e:
      if e[0] == 13:
        raise ConfigPermissionError()
    fn = os.path.join(dir, 'config.txt')
    f = open(fn, 'w')
    # and so on...

    save_config({'port': 500})
  except ConfigPermissionError:
    # do some workaround here
    print 'Config not saved due to permissions'

More information about the Python-list mailing list