Probability Calculator test

Hi,

I am struggling to figure out why my code is failing all 3 tests… I couldn’t even have any clue why it fails the 1st one (“contents”)… I tested the code standalone for “hat.contents” and it produces the results as expected but in the test results on replit it shows strange results (additional elements or incorrect number of elements) that I couldn’t figure out why…:persevere:

This is my code:

class Hat:
    contents = list()
    def __init__(self, **balls):
        # balls are passed in as a dict
        self.balls = balls
        # convert self.balls from a dict to a list named self.contents
        for item in balls:
            for i in range(balls.get(item)):
                self.contents.append(item)

    def draw(self, num2draw):
        if num2draw >= len(self.contents):
            return self.contents
        else:
            ballsDrawn = random.sample(list(enumerate(self.contents)), num2draw)
            newContents = list()
            ballsDrawn_list = list()
            for id, ball in ballsDrawn:
                ballsDrawn_list.append(ball)
            for id, ball in list(enumerate(self.contents)):
                if not (id, ball) in ballsDrawn:
                    newContents.append(ball)
            self.contents = newContents
            return ballsDrawn_list

def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
    allMatchedCount = 0
    num_cycle = num_experiments
    contents = copy.deepcopy(hat.contents)
    while num_cycle > 0:
        hat.contents = copy.deepcopy(contents)
        ballsDrawn = hat.draw(num_balls_drawn)
        ballsDrawn_dict = dict()

        # convert  
        for i in ballsDrawn:
            ballsDrawn_dict[i] = ballsDrawn_dict.get(i, 0) + 1

        # Check if expected balls got drawn
        elem_matchCount = 0
        for ball in expected_balls:
            if ball in ballsDrawn_dict and ballsDrawn_dict[ball] >= expected_balls[ball]:
                elem_matchCount += 1
        if elem_matchCount == len(expected_balls):
            allMatchedCount += 1
        num_cycle -= 1
    
    return allMatchedCount / num_experiments

This is the FAIL msg for the 1st test on “contents” from replit:

======================================================================
FAIL: test_hat_class_contents (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 10, in test_hat_class_contents
    self.assertEqual(actual, expected, 'Expected creation of hat object to add correct contents.')
AssertionError: Lists differ: ['blue', 'blue', 'blue', 'blue', 'red', 're[89 chars]lue'] != ['red', 'red', 'red', 'blue', 'blue']

First differing element 0:
'blue'
'red'

First list contains 12 additional elements.
First extra element 5:
'red'

+ ['red', 'red', 'red', 'blue', 'blue']
- ['blue',
-  'blue',
-  'blue',
-  'blue',
-  'red',
-  'red',
-  'green',
-  'green',
-  'green',
-  'green',
-  'green',
-  'green',
-  'red',
-  'red',
-  'red',
-  'blue',
-  'blue'] : Expected creation of hat object to add correct contents.

FAIL msg for 2nd test:

======================================================================
FAIL: test_hat_draw (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 16, in test_hat_draw
    self.assertEqual(actual, expected, 'Expected hat draw to return two random items from hat contents.')
AssertionError: Lists differ: ['red', 'blue'] != ['blue', 'red']

First differing element 0:
'red'
'blue'

- ['red', 'blue']
+ ['blue', 'red'] : Expected hat draw to return two random items from hat contents.

3rd test FAIL msg:

======================================================================
FAIL: test_prob_experiment (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/boilerplate-probability-calculator/test_module.py", line 26, in test_prob_experiment
    self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
AssertionError: 0.249 != 0.272 within 0.01 delta (0.02300000000000002 difference) : Expected experiment method to return a different probability.

----------------------------------------------------------------------
1 Like

contents is a class variable when written this way, and not an instance variable, so you’re not starting with a clean slate each time you instantiate an object. Add a print(self.contents) at the bottom of your __init__() method and you’ll see what I mean.

1 Like

Oh wow! Thank you very much! I was actually not clear what’s the difference between class variable and instance variable.

I tried adding print(self.contents) at the bottom of init() but still did not see difference (not sure if I missed anything) …, but then, under my curiosity, I tried moving this self.contents = list() inside __init__() and it passed all 3 tests on replit magically… :astonished:

Although I see this is the root for all 3 test fails, I still did not see the difference it makes from the test I tried from my end… I am now trying to find a testcase that proves this produces errors. Thank you very much for pointing this out! :pray:

When I ran it locally, you could see the contents array growing with each test. Locally, it runs main.py which runs a demo and then the tests, so contents gets initialized with the demo, and then the first test adds to that and so on. When you moved the initialization into __init__, it was starting as an empty list every time. In other words, you had correct code, but your initial data was bad after the first run because of the initialization.

1 Like