For the purpose of this discussion, I have the following function:
def countSetBits(num):
cnt = 0
while num:
cnt += num & 0b1
num >>= 1
return cnt
It counts the number of set bits in a given num's binary representation. For example, take 10 whose binary rep is 0b1010 -- countSetBits(10) should equal 2.
I have written a "test suite" that generates random input -- numbers of known set bit count and use that to test my countSetBits function.
import random
import unittest
class TestCountSetBits(unittest.TestCase):
NUM_TESTS = 100
MAX_SET_BIT_CNT = 10
def test_suite(self):
for _ in range(self.NUM_TESTS):
k = expectedCnt = random.randint(0, self.MAX_SET_BIT_CNT)
# Generate a random integer with `k` set bits
setBitPositions = random.sample(range(k * 2), k)
num = sum(0b1 << pos for pos in setBitPositions)
computedCnt = countSetBits(num)
self.assertEqual(computedCnt,
expectedCnt,
msg=f'Got {computedCnt}, but expected {expectedCnt}')
print('Success!')
TestCountSetBits().test_suite()
My questions are:
- Should I use
clsinstead ofself? - Is there a more pythonic way to write this "test suite". I may be reading too much into this, but Python Doc's unittest page has a Basic Example in which each
def test_*has only oneassertEqual. Mydef test_suitehas theassertEqualinside aforloop. Is this bad style? - Any suggestions are welcome! Thanks!
Scrolling down the unittest page, I see subTest which may tidy things up:
class TestCountSetBits(unittest.TestCase):
NUM_TESTS = 100
MAX_SET_BIT_CNT = 10
def test_suite(self):
for _ in range(self.NUM_TESTS):
k = expectedCnt = random.randint(0, self.MAX_SET_BIT_CNT)
# Generate a random integer with `k` set bits
setBitPositions = random.sample(range(k * 2), k)
num = sum(0b1 << pos for pos in setBitPositions)
computedCnt = countSetBits(num)
# Diff starts here
with self.subTest():
self.assertEqual(computedCnt,
expectedCnt,
msg=f'Got {computedCnt}, but expected {expectedCnt}')
# Diff ends here
print('Success!')
TestCountSetBits().test_suite()