0

I would like to write a function that raises an error when it fails and then passes that to unittest. Consider the following:

class undefinedTerms(unittest.TestCase):

    def setUp(self):
        self.A = frozenset((1,2,3,2,1,4,2,5,6,3,5,7,1,5,2,4,8))
        self.B = frozenset((1,4,5,6,3,4,2,5,4,3,1,3,4,2,5,3,6,7,4,2,3,1))
        self.C = frozenset((1,2,3,2,1,4,2,5,6,3,5,7,1,5,2,4))
        self.D = (1,2,1)

    def is_a_set(self,set_this):
        try:
            assert isinstance(set_this, (set,frozenset))
        except TypeError:
            raise TypeError("The object you passed is not a set.")
        return True

    def test_A_is_a_set(self):
         self.assertTrue(self.is_a_set(self.A))

    def test_B_is_a_set(self):
         self.assertTrue(self.is_a_set(self.B))

    def test_C_is_a_set(self):
         self.assertTrue(self.is_a_set(self.C))

    def test_D_is_a_set(self):
         self.assertTrue(self.is_a_set(self.D), self.is_a_set(self.D))


suite = loader.loadTestsFromTestCase(undefinedTerms)
unittest.TextTestRunner(verbosity=2).run(suite)

This gives the following output.

test_A_is_a_set (__main__.undefinedTerms) ... ok
test_B_is_a_set (__main__.undefinedTerms) ... ok
test_C_is_a_set (__main__.undefinedTerms) ... ok
test_D_is_a_set (__main__.undefinedTerms) ... FAIL

======================================================================
FAIL: test_D_is_a_set (__main__.undefinedTerms)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-33-4751f8653e7a>", line 27, in test_D_is_a_set
    self.assertTrue(self.is_a_set(self.D), self.is_a_set(self.D))
  File "<ipython-input-33-4751f8653e7a>", line 12, in is_a_set
    (type(set_this) is set))
AssertionError

----------------------------------------------------------------------
Ran 4 tests in 0.001s

FAILED (failures=1)

What I would like is for the AssertionError to be the TypeError defined in the function. I am open to radically different implementations.

Update

I think I was unclear as to precisely what I am after. After reading comments and answers I believe what I want is to create a custom assertion.

This has previously been addressed here.

Community
  • 1
  • 1
Joshua Cook
  • 12,495
  • 2
  • 35
  • 31
  • 2
    How about `isinstance(set_this, (set, frozenset))`? And why would you expect `except TypeError` to catch an `AssertionError`? Could you explain what you're actually trying to do, and why? – jonrsharpe Nov 06 '15 at 14:13
  • Thanks for the cleaned up assert statement. I don't *expect* anything. I am trying to wrap my head around this assertion thing. – Joshua Cook Nov 06 '15 at 14:16
  • 1
    See https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement - unless *the expression itself* throws an error (which neither `isinstance` nor `type` will, in this case), you'll always get an `AssertionError` from a failing `assert`. – jonrsharpe Nov 06 '15 at 14:17

2 Answers2

1

How about using .assertIsInstance()

def assert_is_set(self, set_this):
        self.assertIsInstance(set_this, (set, frozenset))

At this point, you don't really need a function and can just inline the check.

You can also use the more general .fail() method if your conditions become more complex.

Signals a test failure unconditionally, with msg or None for the error message

if something:
    self.fail("Computer broken!")

The documentation page has a list of all the assertions available in TestCases

Daenyth
  • 35,856
  • 13
  • 85
  • 124
  • I liked your previous suggestion involving `.fail()`. This is a simplified example of something I am trying to do in general. In general, I will seldom have built-in assertion statements that meet my needs. – Joshua Cook Nov 06 '15 at 14:21
  • Would you mind reposting that snippet, perhaps as an optional implementation? – Joshua Cook Nov 06 '15 at 14:23
  • Thanks for your help in thinking about this. I have decided to go with an alternative implementation, but I will continue to think about `.fail()`. – Joshua Cook Nov 06 '15 at 14:41
0

As proposed here, I believe what I was after is custom assertion methods. This is the final implementation I went with.

class SetAssertions:
    def assertIsASet(self, set_this):
        if not isinstance(set_this, (set,frozenset)):
            raise AssertionError("The object you passed is not a set.")

import unittest

class undefinedTerms(unittest.TestCase, SetAssertions):

   def setUp(self):
       self.A = frozenset((1,2,3,2,1,4,2,5,6,3,5,7,1,5,2,4,8))
       self.B = frozenset((1,4,5,6,3,4,2,5,4,3,1,3,4,2,5,3,6,7,4,2,3,1))
       self.C = frozenset((1,2,3,2,1,4,2,5,6,3,5,7,1,5,2,4))
       self.D = (1,2,1)

   def test_A_is_a_set(self):
        self.assertIsASet(self.A)

   def test_B_is_a_set(self):
        self.assertIsASet(self.B)

   def test_C_is_a_set(self):
        self.assertIsASet(self.C)

   def test_D_is_a_set(self):
        self.assertIsASet(self.D)


suite = loader.loadTestsFromTestCase(undefinedTerms)
unittest.TextTestRunner(verbosity=2).run(suite) 

test_A_is_a_set (__main__.undefinedTerms) ... ok
test_B_is_a_set (__main__.undefinedTerms) ... ok
test_C_is_a_set (__main__.undefinedTerms) ... ok
test_D_is_a_set (__main__.undefinedTerms) ... FAIL

======================================================================
FAIL: test_D_is_a_set (__main__.undefinedTerms)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-39-495718fb2bad>", line 32, in test_D_is_a_set
    self.assertIsASet(self.D)
  File "<ipython-input-39-495718fb2bad>", line 6, in assertIsASet
    raise AssertionError("The object you passed is not a set.")
AssertionError: The object you passed is not a set.

----------------------------------------------------------------------
Ran 4 tests in 0.002s

FAILED (failures=1)        
Community
  • 1
  • 1
Joshua Cook
  • 12,495
  • 2
  • 35
  • 31