0

I'm new to Python and I have just started learning how to use classes. I implemented an array-based list with a max size of 50. I also have an append method where self.count refers to the next available position in the list. Now I'm trying to write a unit test for my append method but I'm wondering, how do I check for the assertion error other than appending 50 times? Is there a way to manually change my self.count?

This is my append method.

def append(self,item):
    assert self.count<=50
    if self.count>50:
        raise AssertionError("Array is full")
    self.array[self.count]=item
    self.count+=1

This is what I tried for my unit test:

def testAppend(self):
    a_list=List()
    a_list.append(2)
    self.assertEqual(a_list[0],2)
    # test for assertion error

Any help will be appreciated!

EDIT: Okay after all the useful suggestions I realised I'm supposed to raise an exception instead.

 def append(self,item):
    try:
        self.array[self.count]=item
    except IndexError:
        print('Array is full')
    self.count+=1

Now this is my unit test but I got the warning

Warning (from warnings module):
  File "C:\Users\User\Desktop\task1unitTest.py", line 57
   self.assertRaises(IndexError,a_list.append(6))
 DeprecationWarning: callable is None

.......

def testAppend(self):
    a_list=List()
    a_list.append(2)
    self.assertEqual(a_list[0],2)
    a_list.count=51
    self.assertRaises(IndexError,a_list.append(6))
Sook Lim
  • 541
  • 6
  • 28
  • 1
    Just a note, `AssertionError` will never be raise because the `AssertionError` will be raise first. – TwistedSim May 03 '18 at 18:55
  • Also, assertions can be disabled. Don't use them to enforce invariants in your data structure. – chepner May 03 '18 at 19:03
  • @chepner, as by [this thread](https://stackoverflow.com/questions/40641019/class-invariants-in-python) the python wiki proposes the contrary (for checking data structure invariants, maybe this is not enforcing). Could you elaborate a bit on why not use assertions for this purpose. – Quickbeam2k1 May 03 '18 at 19:08
  • Yes, they are useful for checking invariants, until someone [runs your code without assertions](https://stackoverflow.com/questions/1273211/disable-assertions-in-python?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa). They are not so useful for *enforcing* invariants. – chepner May 03 '18 at 19:15
  • 1
    `assertRaise` takes a function to call and its arguments as separate arguments, not the result of calling it. `self.assertRaises(IndexError, a_list.append, 6)`. – chepner May 03 '18 at 19:22

2 Answers2

2

Rather than adjust the count attribute directly, just append to it 50 times to get a full list.

def test_append_full(self):
    a = List()
    for i in range(50):
        a.append(i)
    with self.assertRaises(AssertionError):
        a.append(0)

This ensures your test does not depend on any implementation-specific details of how you cap the list size. Suppose that you changed List.append to count down from 50 instead of counting up from 0? This test doesn't care; it will test for the AssertionError no matter how you decide to raise it.


Note that assertions can be disabled at run-time; they are more appropriate for debugging. Instead, define your own exception to be raised when an attempt is made to append to a full list:

class ListFullError(RuntimeError):
    pass


def append(self,item):
    if self.count > 50:
        raise ListFullError
    self.array[self.count] = item
    self.count += 1
chepner
  • 497,756
  • 71
  • 530
  • 681
1

If all you want is to test the moment self.count is above 50, you could simply set self.count to 51:

a_list=List()
a_list.count = 51
a_list.append(2)

Your objects count attribute is set to 51 and an exception will be raised.

Alexandre Cox
  • 510
  • 3
  • 9