I ran a test of a simple application that converts roman numeral to
integer and vice versa (taken from Mike Pilgrim's
http://diveintopython.org/ ).
In a test that checks all 4999 possible numbers, unittest performs in
about 125 mSeconds, while py.test takes about 3.8 seconds.  That's 30
times slower.
The unittest and py.test driven scripts perform the same tests.
I've tried to convert the Pilgrim's unittest examples to Py.test too,
and I think the performance using simple asserts inside loops was
acceptable. But using generative tests, I was tremendouly slow.

I you people think attachment is a bad idea, I can think of another
way to share the code I'm talking about.


--
EduardoOPadoan (eopadoan->altavix::com)
Bookmarks: http://del.icio.us/edcrypt
Blog: http://edcrypt.blogspot.com
Jabber: edcrypt at jabber dot org
ICQ: 161480283
GTalk: eduardo dot padoan at gmail dot com
MSN: eopadoan at altavix dot com
"""Unit test for roman.py

This program is part of "Dive Into Python", a free Python book for
experienced programmers.  Visit http://diveintopython.org/ for the
latest version.
"""

__author__ = "Mark Pilgrim ([EMAIL PROTECTED])"
__version__ = "$Revision: 1.2 $"
__date__ = "$Date: 2004/05/05 21:57:19 $"
__copyright__ = "Copyright (c) 2001 Mark Pilgrim"
__license__ = "Python"

import roman
import unittest

class KnownValues(unittest.TestCase):
	knownValues = ( (1, 'I'),
					(2, 'II'),
					(3, 'III'),
					(4, 'IV'),
					(5, 'V'),
					(6, 'VI'),
					(7, 'VII'),
					(8, 'VIII'),
					(9, 'IX'),
					(10, 'X'),
					(50, 'L'),
					(100, 'C'),
					(500, 'D'),
					(1000, 'M'),
					(31, 'XXXI'),
					(148, 'CXLVIII'),
					(294, 'CCXCIV'),
					(312, 'CCCXII'),
					(421, 'CDXXI'),
					(528, 'DXXVIII'),
					(621, 'DCXXI'),
					(782, 'DCCLXXXII'),
					(870, 'DCCCLXX'),
					(941, 'CMXLI'),
					(1043, 'MXLIII'),
					(1110, 'MCX'),
					(1226, 'MCCXXVI'),
					(1301, 'MCCCI'),
					(1485, 'MCDLXXXV'),
					(1509, 'MDIX'),
					(1607, 'MDCVII'),
					(1754, 'MDCCLIV'),
					(1832, 'MDCCCXXXII'),
					(1993, 'MCMXCIII'),
					(2074, 'MMLXXIV'),
					(2152, 'MMCLII'),
					(2212, 'MMCCXII'),
					(2343, 'MMCCCXLIII'),
					(2499, 'MMCDXCIX'),
					(2574, 'MMDLXXIV'),
					(2646, 'MMDCXLVI'),
					(2723, 'MMDCCXXIII'),
					(2892, 'MMDCCCXCII'),
					(2975, 'MMCMLXXV'),
					(3051, 'MMMLI'),
					(3185, 'MMMCLXXXV'),
					(3250, 'MMMCCL'),
					(3313, 'MMMCCCXIII'),
					(3408, 'MMMCDVIII'),
					(3501, 'MMMDI'),
					(3610, 'MMMDCX'),
					(3743, 'MMMDCCXLIII'),
					(3844, 'MMMDCCCXLIV'),
					(3888, 'MMMDCCCLXXXVIII'),
					(3940, 'MMMCMXL'),
					(3999, 'MMMCMXCIX'),
					(4000, 'MMMM'),
					(4500, 'MMMMD'),
					(4888, 'MMMMDCCCLXXXVIII'),
					(4999, 'MMMMCMXCIX'))

	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)

	def testFromRomanKnownValues(self):
		"""fromRoman should give known result with known input"""
		for integer, numeral in self.knownValues:
			result = roman.fromRoman(numeral)
			self.assertEqual(integer, result)

class ToRomanBadInput(unittest.TestCase):
	def testTooLarge(self):
		"""toRoman should fail with large input"""
		self.assertRaises(roman.OutOfRangeError, roman.toRoman, 5000)

	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 testDecimal(self):
		"""toRoman should fail with non-integer input"""
		self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)

class FromRomanBadInput(unittest.TestCase):
	def testTooManyRepeatedNumerals(self):
		"""fromRoman should fail with too many repeated numerals"""
		for s in ('MMMMM', '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)

	def testBlank(self):
		"""fromRoman should fail with blank string"""
		self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, "")

class SanityCheck(unittest.TestCase):
	def testSanity(self):
		"""fromRoman(toRoman(n))==n for all n"""
		for integer in range(1, 5000):
			numeral = roman.toRoman(integer)
			result = roman.fromRoman(numeral)
			self.assertEqual(integer, result)

class CaseCheck(unittest.TestCase):
	def testToRomanCase(self):
		"""toRoman should always return uppercase"""
		for integer in range(1, 5000):
			numeral = roman.toRoman(integer)
			self.assertEqual(numeral, numeral.upper())

	def testFromRomanCase(self):
		"""fromRoman should only accept uppercase input"""
		for integer in range(1, 5000):
			numeral = roman.toRoman(integer)
			roman.fromRoman(numeral.upper())
			self.assertRaises(roman.InvalidRomanNumeralError,
							  roman.fromRoman, numeral.lower())

if __name__ == "__main__":
	unittest.main()
"""Unit test for roman.py

This program is part of "Dive Into Python", a free Python book for
experienced programmers.  Visit http://diveintopython.org/ for the
latest version.
"""

__author__ = "Mark Pilgrim ([EMAIL PROTECTED])"
__version__ = "$Revision: 1.2 $"
__date__ = "$Date: 2004/05/05 21:57:19 $"
__copyright__ = "Copyright (c) 2001 Mark Pilgrim"
__license__ = "Python"

import roman
from py import test


class TestKnownValues:

        
        known_values = ( (1, 'I'),
                         (2, 'II'),
                         (3, 'III'),
                         (4, 'IV'),
                         (5, 'V'),
                         (6, 'VI'),
                         (7, 'VII'),
                         (8, 'VIII'),
                         (9, 'IX'),
                         (10, 'X'),
                         (50, 'L'),
                         (100, 'C'),
                         (500, 'D'),
                         (1000, 'M'),
                         (31, 'XXXI'),
                         (148, 'CXLVIII'),
                         (294, 'CCXCIV'),
                         (312, 'CCCXII'),
                         (421, 'CDXXI'),
                         (528, 'DXXVIII'),
                         (621, 'DCXXI'),
                         (782, 'DCCLXXXII'),
                         (870, 'DCCCLXX'),
                         (941, 'CMXLI'),
                         (1043, 'MXLIII'),
                         (1110, 'MCX'),
                         (1226, 'MCCXXVI'),
                         (1301, 'MCCCI'),
                         (1485, 'MCDLXXXV'),
                         (1509, 'MDIX'),
                         (1607, 'MDCVII'),
                         (1754, 'MDCCLIV'),
                         (1832, 'MDCCCXXXII'),
                         (1993, 'MCMXCIII'),
                         (2074, 'MMLXXIV'),
                         (2152, 'MMCLII'),
                         (2212, 'MMCCXII'),
                         (2343, 'MMCCCXLIII'),
                         (2499, 'MMCDXCIX'),
                         (2574, 'MMDLXXIV'),
                         (2646, 'MMDCXLVI'),
                         (2723, 'MMDCCXXIII'),
                         (2892, 'MMDCCCXCII'),
                         (2975, 'MMCMLXXV'),
                         (3051, 'MMMLI'),
                         (3185, 'MMMCLXXXV'),
                         (3250, 'MMMCCL'),
                         (3313, 'MMMCCCXIII'),
                         (3408, 'MMMCDVIII'),
                         (3501, 'MMMDI'),
                         (3610, 'MMMDCX'),
                         (3743, 'MMMDCCXLIII'),
                         (3844, 'MMMDCCCXLIV'),
                         (3888, 'MMMDCCCLXXXVIII'),
                         (3940, 'MMMCMXL'),
                         (3999, 'MMMCMXCIX'),
                         (4000, 'MMMM'),
                         (4500, 'MMMMD'),
                         (4888, 'MMMMDCCCLXXXVIII'),
                         (4999, 'MMMMCMXCIX')) 
        
        def to_roman_known_values(self, integer, numeral):
                result = roman.toRoman(integer)
                assert numeral == result

        def from_roman_known_values(self, integer, numeral):
                result = roman.fromRoman(numeral)
                assert integer == result

        def test_to_roman_known_values(self):
                """toRoman should give known result with known input"""
                for integer, numeral in self.known_values:
                        yield self.to_roman_known_values, integer, numeral

        def test_from_roman_known_values(self):
                """fromRoman should give known result with known input"""
                for integer, numeral in self.known_values:
                        yield self.from_roman_known_values, integer, numeral


class TestToRomanBadInput:

        def out_of_range(self, integer):
                test.raises(roman.OutOfRangeError, roman.toRoman, integer)

        def test_out_of_range(self):
                """toRoman should fail:
                - with too large input
                - with 0 input
                - with negative input
                """
                for integer, msg in (5000, 0, -1):
                        print 'Fail on:', integer
                        yield self.out_of_range, integer

        def test_decimal(self):
                """toRoman should fail with non-integer input"""
                test.raises(roman.NotIntegerError, roman.toRoman, 0.5)


class TestFromRomanBadInput:

        def invalid_romam_numeral(self, s):
                test.raises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
        
        def test_too_many_repeated_numerals(self):
                """fromRoman should fail with too many repeated numerals"""
                for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
                        print 'Fail on:', s
                        yield self.invalid_romam_numeral, s

        def test_repeated_pairs(self):
                """fromRoman should fail with repeated pairs of numerals"""
                for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
                        print 'Fail on:', s
                        yield self.invalid_romam_numeral, s

        def test_malformed_antecedent(self):
                """fromRoman should fail with malformed antecedents"""
                for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
                                  'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
                        print 'Fail on:', s
                        yield self.invalid_romam_numeral, s

        def test_blank(self):
                """fromRoman should fail with blank string"""
                yield self.invalid_romam_numeral, ''
                

class TestSanityCheck:

        def sanity(self, integer):
                numeral = roman.toRoman(integer)
                result = roman.fromRoman(numeral)
                assert integer == result
        
        def test_sanity(self):
                """fromRoman(toRoman(n))==n for all n"""
                for integer in range(1, 5000):
                        print 'Fail on:', integer
                        yield self.sanity, integer
                        

class TestCaseCheck:

        def to_romam_up(self, integer):
                numeral = roman.toRoman(integer)
                assert numeral == numeral.upper()

        def from_romam_up(self, integer):
                numeral = roman.toRoman(integer)
                roman.fromRoman(numeral.upper())
                test.raises(roman.InvalidRomanNumeralError,
                            roman.fromRoman, numeral.lower())

        
        def test_to_roman_case(self):
                """toRoman should always return uppercase"""
                for integer in range(1, 5000):
                        print "Fail on:", integer
                        yield self.to_romam_up, integer

        def test_from_roman_case(self):
                """fromRoman should only accept uppercase input"""
                for integer in range(1, 5000):
                        print "Fail on:", integer
                        yield self.from_romam_up, integer
_______________________________________________
py-dev mailing list
py-dev@codespeak.net
http://codespeak.net/mailman/listinfo/py-dev

Reply via email to