Continuing in Python's Unittest When an Assertion Fails

Continuing in Python's unittest when an assertion fails

Another way to have non-fatal assertions is to capture the assertion exception and store the exceptions in a list. Then assert that that list is empty as part of the tearDown.

import unittest

class Car(object):
def __init__(self, make, model):
self.make = make
self.model = make # Copy and paste error: should be model.
self.has_seats = True
self.wheel_count = 3 # Typo: should be 4.

class CarTest(unittest.TestCase):
def setUp(self):
self.verificationErrors = []

def tearDown(self):
self.assertEqual([], self.verificationErrors)

def test_init(self):
make = "Ford"
model = "Model T"
car = Car(make=make, model=model)
try: self.assertEqual(car.make, make)
except AssertionError, e: self.verificationErrors.append(str(e))
try: self.assertEqual(car.model, model) # Failure!
except AssertionError, e: self.verificationErrors.append(str(e))
try: self.assertTrue(car.has_seats)
except AssertionError, e: self.verificationErrors.append(str(e))
try: self.assertEqual(car.wheel_count, 4) # Failure!
except AssertionError, e: self.verificationErrors.append(str(e))

if __name__ == "__main__":
unittest.main()

How can I continue a unit test after an assert fails?

From your test it seems you are trying to test the id property of class City. So you can test those two instances you defined at setUp have a correct value set - similar to what you did:

def testIdProperty(self):
self.assertEqual(1, self.city1.id_city, "Fail if City1 does not have id 1")
self.assertEqual(2, self.city2.id_city, "Fail if City2 does not have id 2")

Now when you run this test it should pass. If some day you break your code and one of these two asserts fails, you want to see it when you run your tests and fix it.

But, if for some reason you don't want these asserts to fail temporarily until you come back to finishing up the test later, then you can skip that test like this:

@unittest.skip("skip this test im not done writing it yet!")
def testIdProperty(self):
self.assertEqual(1, self.city1.id_city, "Fail if City1 does not have id 1")
self.assertEqual(2, self.city2.id_city, "Fail if City2 does not have id 2")

EDIT: OK if you want to suppress errors from failing asserts don't do a try/except in every place you need it. It's better to write a generic function outside your test class:

def silent_assert(func, *args, **kwargs):
try:
func(*args, **kwargs)
except Exception as exc:
print exc.message

And have this call your assert, so it will run the code and only print the error silently if it fails:

def testIdProperty(self):
silent_assert(self.assertEqual, 1, self.city1.id_city, "City1 does not have id 1")
silent_assert(self.assertEqual, 2, self.city2.id_city, "City2 does not have id 2")

You will be able to call any asserts on it and pass any number of arguments each one accepts. Not sure if it's a good idea to hide errors like this, I never had to do it but that's just me, everyone has their organizational style!

Python Unittests continue after failure

You have to separate each test case into different method. To make it easier to create new test / save typing time, you can auto-generate test case based on input like this

#!/usr/env/bin python2.7

import unittest
from fib import fib

class FibTests(unittest.TestCase):
pass

def test_gen(expected, actual):
def test_method(self):
return self.assertEqual(expected, actual)
return test_method

if __name__ == '__main__':
cases = ((fib(1), 1), (fib(2), 1), (fib(5), 5))
for index, case in enumerate(cases):
test_name = 'test_{0}'.format(index)
test = test_gen(case[1], case[0])
setattr(FibTests, test_name, test)
suite = unittest.TestLoader().loadTestsFromTestCase(FibTests)
result = unittest.TextTestRunner(verbosity=2).run(suite)

How do you test that a Python function throws an exception?

Use TestCase.assertRaises (or TestCase.failUnlessRaises) from the unittest module, for example:

import mymod

class MyTestCase(unittest.TestCase):
def test1(self):
self.assertRaises(SomeCoolException, mymod.myfunc)

Python unittest call function when assertion fails

You can use ordinal try/except statement:

from exceptions import AssertionError as AE

class TestAuto(unittest.TestCase):
def test_not_fail(self):
# won't call func1
try:
self.assertEqual(1, 1)
except AE:
self.func1()
raise

def test_fail(self):
# will call func1
try:
self.assertEqual(1, 9)
except AE:
self.func1()
raise

def func1(self):
print 'We are inside'

It can be implemented as a decorator for convenient usage:

from exceptions import AssertionError as AE

def run_if_test_fails(call_on_fail):
def deco(f):
def inner(*args, **kwargs):
try:
f(*args, **kwargs)
except AE:
# test failed - run callback
call_on_fail()
# reraise Error to mark it in result
raise
return inner
return deco

def func1():
print('We are inside')

class TestAuto(unittest.TestCase):

@run_if_test_fails(func1)
def test_not_fail(self):
# won't call func1
self.assertEqual(1, 1)

@run_if_test_fails(func1)
def test_fail(self):
# will call func1
self.assertEqual(1, 9)

Why do I get an Assertion Error when patching a class with unittest?

As @MrBeanBremen pointed out in his comment, where the classes are being patched is key. In my question, I was patching them at the source, but since they were imported into my interface.py file, they need to be patched in that location.

Also, since SiteMetaData is instantiated at the global level, its instance needs to be patched rather than the class itself. Since, EdgeAPIRoutes is instantiated within the get_route_list function, the class itself needs to be patched. Then to assign return values to the EdgeAPIRoutes's instance methods, the return_value of the patched class needs to be used:

mock_edge_api_routes_class.return_value.get_route_list.return_value = [                                                            
example_route_list,
error_response
]

Since the site_meta_data instance is patched directly, the instance method values can be assigned directly in the patch:

mock_site_meta_data.get_edge_api_inputs.return_value = [
edge_inputs["edge_site"],
edge_inputs["edge_key"],
error_response
]

interface.py

import logging
from repo.site_meta_data import SiteMetaData
from repo.routes import EdgeAPIRoutes
from usecase import response_objects

interfacelog = logging.getLogger(__name__)

site_meta_data = SiteMetaData()

def get_route_list(request):
"""
"""

interfacelog.info("running get_route_list")

if bool(request):
repo_type, repo_type_error = site_meta_data.get_repo_type(request.filters["parent_company"],
request.filters["site"])

if repo_type_error is not None:
'''
handle any get repo type system errors
'''
pass
if repo_type == "Minestar Edge":
edge_site, edge_key, edge_error = site_meta_data.get_edge_api_inputs(request.filters["parent_company"],
request.filters["site"])
ear = EdgeAPIRoutes(edge_site, edge_key)
rl, routes_error = ear.get_route_list(request.filters["start_date"],
request.filters["end_date"])

if routes_error is not None:
'''
handle any get routes system error
'''
pass

success_resp = response_objects.ResponseSuccess()
success_resp.value = {"routes" : rl}

return success_resp
else:
'''
handle and errors due to an invalid request
'''
return response_objects.ResponseFailure.build_from_invalid_request_object(request)

test_interface function patch setup

@patch("usecase.interface.EdgeAPIRoutes")
@patch("usecase.interface.site_meta_data")
def test_get_route_list_repo_interface_edge(self, mock_site_meta_data,
mock_edge_api_routes_class):
"""
Test that SiteMetaData.get_route_list is used
appropriately and returns expected values from
mock as a valid response object
"""
...

Python unittest failure when results appear equal

Ok, I found the difference. Python 3 has more support for unicode, but it doesn't show the encoding that is in effect when printing a unicode string, which is why they printed the same even though they had different types:

  1. <class '__main__.Pica'>
  2. <class 'str'>

In order for the assertion to work, either a smarter compare is needed, or else the strings need to be put in a common format before calling the assert methods.



Related Topics



Leave a reply



Submit