简体   繁体   中英

Python 3.x UnitTest module disable SystemExit stack trace output

I'm learning how to write unit tests using the unittest module and have jumped in to deep end with meta programming (I believe it's also known as monkey patching) but have a stack trace that is printing out during a failed assertion test.

<output cut for brevity>
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py", line 203, in __exit__
    self._raiseFailure("{} not raised".format(exc_name))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py", line 135, in _raiseFailure
    raise self.test_case.failureException(msg)
AssertionError: SystemExit not raised

Seems like I should be getting this error as the test should fail but I would prefer it be a bit more presentable and exclude the whole stack trace along with the assertion error.

Here's the code that uses a context manager to check for SystemExit:

with self.assertRaises(SystemExit) as cm:
    o_hue_user.getHueLoginAuthentication()
self.assertNotEqual(cm.exception.code, 0)

The getHueLoginAuthentication method does execute exit(1) upon realizing the user name or password are incorrect but I need to eliminate the stack trace being printed out.

BTW, I've searched this and other sites and cannot find an answer that seems to have a simple or complete solution.

Thanks!


Since I'm new to this forum, I'm not sure if this is the correct way to respond to the answer...

I can try to put in the key areas of code but I can't reveal too much code as I'm working for a financial institute and they have strict rules about sharing internal work.

To answer your question, this is the code that executes the exit():

authentication_fail_check = bool(re.search('Invalid username or password', r.text))
if (r.status_code != 200 or authentication_fail_check) :
    self.o_logging_utility.logger.error("Hue Login failed...")
    exit(1)

I use PyCharm to debug. The key point of this code is to return an unsuccessful execution so that I can stop execution if this error occurs. I don't think it's necessary to use a try block here but I would not think it would matter. What's your professional opinion? When the assertion condition is met, I get a pass and no trace stack. All this appears to be telling me is, the assertion was not met. My assertion tests are working. All I want to do is get rid of the trace stack and just print the last line of: "AssertionError: SystemExit not raised" How do I get rid of the stack trace and leave the last line of the output as feedback?

Thanks!


I meant to say thank you for the warm welcome as well Don.

BTW, I can post the test code as it is not a part of the main code base. This is my first meta programming (monkey patching) unit test and actually my second unit test. I'm still struggling with going through the trouble of building some code that will tell me I get a particular result that I know I will get anyway. In the example of a function that returns a false boolean for example, If I write code that says execute this code with these parameters and I know for a fact that these values will return false, then why build code that tells me it will return false? I'm struggling with how to design good tests that won't tell me the blatantly obvious.

So far, all I have managed to do is use a unit test to tell me if, when I instantiate an object and execute a function, it tells me if the login was successful or not. I can change the inputs to cause it to fail. But I already know it will fail. If I understand unit tests correctly, when I test if a login is successful or not, it is more of an integration test rather than a unit test. However, the problem is, this particular class that I'm testing gets its parameters from a configuration file and sets instance variables for the specific connection. In the test code, I have 2 sets of tests that represents a good login and a bad login. I know unit tests are more autonomous in that the function can be called with parameters and tested independently. However, this is not how this code works. So, I'm at a loss as to how to design an efficient and useful test.

This is the test code for the specific class:

import unittest
from HueUser import *

test_data = \
    {
        "bad_login": {"hue_protocol": "https",
                      "hue_server": "my.server.com",
                      "hue_service_port": "1111",
                      "hue_auth_url": "/accounts/login/?next=/",
                      "hue_user": "baduser",
                      "hue_pw": "badpassword"},
        "good_login": {"hue_protocol": "https",
                       "hue_server": "my.server.com",
                       "hue_service_port": "1111",
                       "hue_auth_url": "/accounts/login/?next=/",
                       "hue_user": "mouser",
                       "hue_pw": "good password"}
    }

def hue_test_template(*args):
    def foo(self):
        self.assert_hue_test(*args)
    return foo

class TestHueUserAuthentication(unittest.TestCase):
    def assert_hue_test(self,o_hue_user):
        with self.assertRaises(SystemExit) as cm:
            o_hue_user.getHueLoginAuthentication()
        self.assertNotEqual(cm.exception.code, 0)

for behaviour, test_cases in test_data.items():
    o_hue_user = HueUser()
    for name in test_cases:
        setattr(o_hue_user, name, test_cases[name])
    test_name = "test_getHueLoginAuthentication_{0}".format(behaviour)
    test_case = hue_test_template(o_hue_user)
    setattr(TestHueUserAuthentication,test_name, test_case)

Let me know how to respond to Answers or if I should just edit my post???

Thanks!

Welcome to Stack Overflow, Robert. It would be really helpful if you included a full example so other people can help you find the problem.

With the information you've given, I would guess that getHueLoginAuthentication() isn't actually raising the error you think it is. Try using a debugger to follow what it's doing, or put a print statement in just before it calls exit() .

Here's a full example that shows how assertRaises() works:

from unittest import TestCase


def foo():
    exit(1)


def bar():
    pass


class FooTest(TestCase):
    def test_foo(self):
        with self.assertRaises(SystemExit):
            foo()

    def test_bar(self):
        with self.assertRaises(SystemExit):
            bar()

Here's what happens when I run it:

$ python3.6 -m unittest scratch.py
F.
======================================================================
FAIL: test_bar (scratch.FooTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "scratch.py", line 19, in test_bar
    bar()
AssertionError: SystemExit not raised

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM