DiveIntoPython(十二)
英文书地址:
http://diveintopython.org/toc/index.html
Chapter 13.Unit Testing
13.1.Introduction to Roman numerals
roman.py
13.2.Diving in
Python has a framework for unit testing, the appropriately-named unittest module.
13.3.Introducing romantest.py
example 13.1.romantest.py
import roman
import unittest
class KnownValues(unittest.TestCase):
...snip..
def testToRomanKnownValues(self):
"""toRoman should give known result with known input"""
for integer, numeral in self.knownValues:
result = roman.toRoman(integer)
self.assertEqual(numeral, result)
...snip...
if __name__ == "__main__":
unittest.main()
13.4.Testing for success
A test case should be able to...
1.run completely by itself, without any human input. Unit testing is about automation.
2.determine by itself whether the function it is testing has passed or failed, without a human interpreting the results.
3.run in isolation, separate from any other test cases (even if they test the same functions). Each test case is an island.
example 13.2.testToRomanKnownVallues
import roman
import unittest
class KnownValues(unittest.TestCase):
knownValues = ( (1, 'I'),
(2, 'II'),
(3, 'III'),
(4, 'IV'),
(3999, 'MMMCMXCIX'))
def testToRomanKnownValues(self):
"""toRoman should give known result with known input"""
for integer, numeral in self.knownValues:
result = roman.toRoman(integer)
self.assertEqual(numeral, result)
if __name__ == "__main__":
unittest.main()
13.5.Testing for Failure
the unittest module provides methods for testing whether a function raises a particular exception when given bad input.
example 13.3.Testing bad input to toRoman
class ToRomanBadInput(unittest.TestCase):
def testTooLarge(self):
"""toRoman should fail with large input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, 4000)
def testZero(self):
"""toRoman should fail with 0 input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0)
def testNegative(self):
"""toRoman should fail with negative input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1)
def testNonInteger(self):
"""toRoman should fail with non-integer input"""
self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)
example 13.4.Testing bad input to fromRoman
class FromRomanBadInput(unittest.TestCase):
def testTooManyRepeatedNumerals(self):
"""fromRoman should fail with too many repeated numerals"""
for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
def testRepeatedPairs(self):
"""fromRoman should fail with repeated pairs of numerals"""
for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
def testMalformedAntecedent(self):
"""fromRoman should fail with malformed antecedents"""
for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
13.6.Testing for sanity sanity ['sænəti] n. 明智;头脑清楚;精神健全;通情达理,合乎逻辑
usually in the form of conversion functions where one converts A to B and the other converts B to A. In these cases, it is useful to create a “sanity check” to make sure that you can convert A to B and back to A without losing precision, incurring rounding errors, or triggering any other sort of bug.
example 13.5.Testing toRoman against fromRoman
class SanityCheck(unittest.TestCase):
def testSanity(self):
"""fromRoman(toRoman(n))==n for all n"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
result = roman.fromRoman(numeral)
self.assertEqual(integer, result)
example 13.6.Testing for case
class CaseCheck(unittest.TestCase):
def testToRomanCase(self):
"""toRoman should always return uppercase"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
self.assertEqual(numeral, numeral.upper())
def testFromRomanCase(self):
"""fromRoman should only accept uppercase input"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
roman.fromRoman(numeral.upper())
self.assertRaises(roman.InvalidRomanNumeralError,
roman.fromRoman, numeral.lower())
英文书地址:
http://diveintopython.org/toc/index.html
Chapter 13.Unit Testing
13.1.Introduction to Roman numerals
roman.py
13.2.Diving in
Python has a framework for unit testing, the appropriately-named unittest module.
13.3.Introducing romantest.py
example 13.1.romantest.py
import roman
import unittest
class KnownValues(unittest.TestCase):
...snip..
def testToRomanKnownValues(self):
"""toRoman should give known result with known input"""
for integer, numeral in self.knownValues:
result = roman.toRoman(integer)
self.assertEqual(numeral, result)
...snip...
if __name__ == "__main__":
unittest.main()
13.4.Testing for success
A test case should be able to...
1.run completely by itself, without any human input. Unit testing is about automation.
2.determine by itself whether the function it is testing has passed or failed, without a human interpreting the results.
3.run in isolation, separate from any other test cases (even if they test the same functions). Each test case is an island.
example 13.2.testToRomanKnownVallues
import roman
import unittest
class KnownValues(unittest.TestCase):
knownValues = ( (1, 'I'),
(2, 'II'),
(3, 'III'),
(4, 'IV'),
(3999, 'MMMCMXCIX'))
def testToRomanKnownValues(self):
"""toRoman should give known result with known input"""
for integer, numeral in self.knownValues:
result = roman.toRoman(integer)
self.assertEqual(numeral, result)
if __name__ == "__main__":
unittest.main()
13.5.Testing for Failure
the unittest module provides methods for testing whether a function raises a particular exception when given bad input.
example 13.3.Testing bad input to toRoman
class ToRomanBadInput(unittest.TestCase):
def testTooLarge(self):
"""toRoman should fail with large input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, 4000)
def testZero(self):
"""toRoman should fail with 0 input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0)
def testNegative(self):
"""toRoman should fail with negative input"""
self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1)
def testNonInteger(self):
"""toRoman should fail with non-integer input"""
self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)
example 13.4.Testing bad input to fromRoman
class FromRomanBadInput(unittest.TestCase):
def testTooManyRepeatedNumerals(self):
"""fromRoman should fail with too many repeated numerals"""
for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
def testRepeatedPairs(self):
"""fromRoman should fail with repeated pairs of numerals"""
for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
def testMalformedAntecedent(self):
"""fromRoman should fail with malformed antecedents"""
for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
13.6.Testing for sanity sanity ['sænəti] n. 明智;头脑清楚;精神健全;通情达理,合乎逻辑
usually in the form of conversion functions where one converts A to B and the other converts B to A. In these cases, it is useful to create a “sanity check” to make sure that you can convert A to B and back to A without losing precision, incurring rounding errors, or triggering any other sort of bug.
example 13.5.Testing toRoman against fromRoman
class SanityCheck(unittest.TestCase):
def testSanity(self):
"""fromRoman(toRoman(n))==n for all n"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
result = roman.fromRoman(numeral)
self.assertEqual(integer, result)
example 13.6.Testing for case
class CaseCheck(unittest.TestCase):
def testToRomanCase(self):
"""toRoman should always return uppercase"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
self.assertEqual(numeral, numeral.upper())
def testFromRomanCase(self):
"""fromRoman should only accept uppercase input"""
for integer in range(1, 4000):
numeral = roman.toRoman(integer)
roman.fromRoman(numeral.upper())
self.assertRaises(roman.InvalidRomanNumeralError,
roman.fromRoman, numeral.lower())