Including edge and corner cases

When we move to testing the Deck class as a whole, we'll need to have some things confirmed: that it produces all of the required Cards class, and that it actually shuffles properly. We don't really need to test that it deals properly because we're depending on the list and list.pop() method; as these are first-class parts of Python, they don't require additional testing.

We'd like to test the Deck class construction and shuffling independently of any specific Card class hierarchy. As noted previously, we can use a factory function to make the two Deck and Card definitions independent. Introducing a factory function introduces yet more testing. Not a bad thing, considering the bugs previously revealed in the Card class hierarchy.

Here's a test of the factory function:

class TestCardFactory(unittest.TestCase):

def test_rank1_should_createAceCard(self) -> None:
c = card(1, Suit.CLUB)
self.assertIsInstance(c, AceCard)

def test_rank2_should_createCard(self) -> None:
c = card(2, Suit.DIAMOND)
self.assertIsInstance(c, Card)

def test_rank10_should_createCard(self) -> None:
c = card(10, Suit.HEART)
self.assertIsInstance(c, Card)

def test_rank10_should_createFaceCard(self) -> None:
c = card(11, Suit.SPADE)
self.assertIsInstance(c, Card)

def test_rank13_should_createFaceCard(self) -> None:
c = card(13, Suit.CLUB)
self.assertIsInstance(c, Card)

def test_otherRank_should_exception(self) -> None:
with self.assertRaises(LogicError):
c = card(14, Suit.DIAMOND)
with self.assertRaises(LogicError):
c = card(0, Suit.DIAMOND)

We didn't test all 13 ranks, as 2 through 10 should all be identical. Instead, we followed this advice from Boris Beizer in the book Software Testing Techniques:

"Bugs lurk in corners and congregate at boundaries."

The test cases involve the edge values for each card range. Consequently, we have test cases for the values 1, 2, 10, 11, and 13, as well as the illegal values 0 and 14. We bracketed each range with the least value, the maximum value, one below the least value, and one above the maximum value.

We've modified the pattern for test naming. In this case, we have several different states being tested. We've modified the simpler names from these to followthe pattern test_StateUnderTest_should_ExpectedBehavior. There doesn't seem to be a compelling reason to break these tests into separate classes to decompose the state under test. 

In the next section, we'll look at ways to handle dependent objects. This will allow us to test each unit in isolation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset