Is there a way to configure Python logging to log

2020-04-08 11:20发布

问题:

I'm running test cases and I'd like to set up a my logging in such a way that it automatically logs all cases where tests fails - but I'd like to get a custom response, for example if an assertion fails I'd like to get the response to a request made by my test, not just default message which assertion failed. At present I only know that the assertion failed, but I don't know what the program returned.

So say I'm testing a view function, for example I have a test which looks roughly likes this (part of whole TestCase class)

def edit_profile(self):
    return self.app.get("/edit_profile", follow_redirects=True)

def test_edit_profile(self):
    rv = self.edit_profile()
    assert "Edit your profile admin" in rv.data

Is there a way for me to configure logging in such a way that each test failure will log rv.data to a logs file?

Currently I simply add logging.debug(rv.data) before the assertion that failed in previous tests, run the test again, debug the issue, and go on, but this is ineffective, it's easy to forget about those loggging.debug() later on, and it would be much faster if I had an function to automatically log my webpage response to test requests if they fail.

回答1:

self.assertIn('Edit your profile admin', rv.data, msg=rv.data)

Use the assertWhatever methods. I don't fully understand why, but you're not supposed to use assert statements for assertions in unittest. (Other frameworks let you assert with assert.)

For reference, adding a message to an assert assertion works as follows:

assert 'Edit your profile admin' in rv.data, rv.data


回答2:

You can do something like this:

def test_edit_profile(self):
    rv = self.edit_profile()
    try:
        assert "Edit your profile admin" in rv.data
    except AssertionError:
        # Do your logging here

Edit: Was pointed out that this takes the assert functionality away basically, since the assertion is handled by the except block. Suggestions welcome.

Edit: This would work, but is pretty sloppy.

def test_edit_profile(self):
    rv = self.edit_profile()
    try:
        assert "Edit your profile admin" in rv.data
    except AssertionError:
        assert "Edit your profile admin" in rv.data
        # Do your logging here


回答3:

Consider replacing assert with a non-throwing check:

def log_assert(arg=None):
    caller = inspect.stack()[1]
    if arg is None:
        with open(caller[1], "r") as source_code:
            for n, line in enumerate(source_code):
                if n >= caller[2] - 1:
                    arg = line.strip
                break
    logger.error("[%s:%d - %s] %s" % (basename(caller[1]), caller[2], caller[3], arg))

...

"Edit your profile admin" in rv.data or log_assert("profile: \"" + str(rv.data) + "\"")

will print:

ERROR [TestCase.py:320 - test_edit_profile] profile: "View your profile admin"