Check that a function raises a warning with nose t

2019-04-07 07:30发布

问题:

I'm writing unit tests using nose, and I'd like to check whether a function raises a warning (the function uses warnings.warn). Is this something that can easily be done?

回答1:

def your_code():
    # ...
    warnings.warn("deprecated", DeprecationWarning)
    # ...

def your_test():
    with warnings.catch_warnings(record=True) as w:
        your_code()
        assert len(w) > 1

Instead of just checking the lenght, you can check it in-depth, of course:

assert str(w.args[0]) == "deprecated"

In python 2.7 or later, you can do this with the last check as:

assert str(w[0].message[0]) == "deprecated"



回答2:

There are (at least) two ways of doing this. You can catch the warning in the list of warnings.WarningMessages in test or use mock to patch the imported warnings in your module.

I think the patch version is more general.

raise_warning.py:

import warnings

def should_warn():
    warnings.warn('message', RuntimeWarning)
    print('didn\'t I warn you?')

raise_warning_tests.py:

import unittest
from mock import patch
import raise_warning

class TestWarnings(unittest.TestCase):

    @patch('raise_warning.warnings.warn')
    def test_patched(self, mock_warnings):
        """test with patched warnings"""
        raise_warning.should_warn()
        self.assertTrue(mock_warnings.called)

    def test_that_catches_warning(self):
        """test by catching warning"""
        with raise_warning.warnings.catch_warnings(True) as wrn:
            raise_warning.should_warn()
            # per-PEP8 check for empty sequences by their Truthiness 
            self.assertTrue(wrn)