E D R , A S I H C RSS

Py Unit

1. Python Unit Testing Framework PyUnit — ๋Œ€•ด„œ

  • ›๋ฌธ€ PyUnit— žˆ๋Š” ๋„๋จผŠธ ๋ฌธ„œž„„ ๋ฐ˜€๋‘ . ๊ณต๋ถ€๊ฒธ 1ฐจ  •๋ฆฌค‘. ผ๋‹จ •ฝ๊ฐ„ ๋ฒˆ—ญž‘—…๋’ค  •๋ฆฌ•จ.
  • PyUnit๋Š” Python — ๊ธฐ๋ณธ œผ๋กœ ฌ•จ๋˜–ดžˆ๋Š” UnitTest Framework libraryด๋‹ค. •˜ง€๋งŒ, UnitTestž‘„— ๋Œ€•œ ๊ธฐ๋ณธ ธ ๊ฐœ๋…๋“ค„ ‰ฝ๊ฒŒ ๋‹ด๊ณ  žˆ๋‹ค๊ณ  ƒ๊ฐ•˜—ฌ ๊ณต๋ถ€ค‘. (†”งžˆ C++๋กœ UnitTest•  —„๋‘ •ˆ๋‚˜„œ. --; Pythonœผ๋กœ ๋จผ € ”„๋กœ† ƒ€ž…ด ๋˜๋Š” ๋ถ€๋ถ„„ ž‘„•˜๊ณ  ๋‹ค๋ฅธ –ธ–ด๋กœ ฌŒ…•˜๋Š” ‹œผ๋กœ • ๊นŒ ƒ๊ฐค‘)

2. ๊ด€๋ จ ‚ฌดŠธ

3. TestCase

unit testing ˜ ๊ฐ€žฅ ๊ธฐ๋ณธ ธ ฝ”๋“œ ๋ธ”๋ก ๋‹จœ„. …‹Œ…๊ณผ ๋ชจ๋“ˆด  œ๋Œ€๋กœ ๋Œ•„๊ฐ€๋Š”ง€๋ฅผ ฒดฌ•˜๊ธฐ œ„•œ •˜๋‚˜˜ ‹œ๋‚˜๋ฆฌ˜ค๊ฐ€ ๋œ๋‹ค.

PyUnit—„œ๋Š” TestCase๋Š” unittest๋ชจ๋“ˆ˜ TestCase ด๋ž˜Šค๋กœ„œ ‘œ˜„๋œ๋‹ค.testcase ด๋ž˜Šค๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด unittest.TestCase๋ฅผ ƒ†๋ฐ›•„„œ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค.

4. ๊ฐ„๋‹จ•œ testcase ˜  œž‘. 'failure', 'error'

๊ฐ€žฅ ๊ฐ„๋‹จ•œ ๋ฐฉ๋ฒ•€ runTest ๋ฉ”†Œ๋“œ๋ฅผ ˜ค๋ฒ„๋ผด๋”ฉ •˜๋Š” ๊ฒƒด๋‹ค.
~cpp 
import unittest

class DefaultWidgetSizeTestCase(unittest.TestCase):
	def runTest(self):
	widget = Widget("The widget")
	assert widget.size() == (50,50), 'incorrect default size'
…ŒŠคŒ…„ •˜๊ธฐ œ„•ด Python˜ assert ๊ตฌ๋ฌธ„ ‚ฌšฉ•œ๋‹ค. testcase๊ฐ€ ‹ค–‰๋  ๋•Œ assertion„ ‹ค–‰•˜๋ฉด AssertionError ๊ฐ€ ผ–ด๋‚˜๊ณ , testing framework๋Š” ด testcase๋ฅผ 'failure' –ˆ๋‹ค๊ณ   •˜•  ๊ฒƒด๋‹ค. 'assert' ๋ฅผ ๋ช…‹œ œผ๋กœ จ๋†“ง€ •Š€ ๋ถ€๋ถ„—„œ˜ ˜ˆ™ธ๊ฐ€ ๋ฐœƒ•œ ๊ฒƒ๋“ค€ testing framework —„œ๋Š” 'errors'๋กœ ๊ฐ„ฃผ•œ๋‹ค.

testcase๋ฅผ ‹ค–‰•˜๋Š” ๋ฐฉ๋ฒ•€ ›„— „ค๋ช…•  ๊ฒƒด๋‹ค. testcase ด๋ž˜Šค๋ฅผ ƒ„•˜๊ธฐ œ„•ด šฐ๋ฆฌ๋Š” ƒ„ž— •„๋ฌด ธž —†ด ˜ธถœ•ดฃผ๋ฉด ๋œ๋‹ค.
~cpp 
testCase = DefaultWidgetSizeTestCase ()

5. žฌ‚ฌšฉ•˜๋Š” set-up code : 'fixtures' ๋งŒ๋“ค๊ธฐ.

๋งŒผ testcase๊ฐ€ ๋งŽ•„ง€๋ฉด ๊ทธ๋“ค˜ set-up ฝ”๋“œ๋“ค๋„ ค‘๋ณต๋  ๊ฒƒด๋‹ค. ๋งค๋ฒˆ Widget ด๋ž˜Šค๋ฅผ …ŒŠคŠธ•˜๊ธฐ œ„•ด ด๋ž˜Šค๋“ค๋งˆ๋‹ค widget ธŠค„Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ€ ๋ช…๋ฐ•œ ค‘๋ณตด๋‹ค.
๋‹ค–‰Šค๋Ÿฝ๊ฒŒ๋„ šฐ๋ฆฌ๋Š” setUp ๋ผ๋Š”, testing framework๊ฐ€ …ŒŠคŒ…„ • ๋•Œ ž๋™œผ๋กœ ˜ธถœ•ดฃผ๋Š” ๋ฉ”†Œ๋“œ๋ฅผ ๊ตฌ˜„•จœผ๋กœ„œ •ด๊ฒฐ•  ˆ˜ žˆ๋‹ค.

~cpp 
import unittest

class SimpleWidgetTestCase(unittest.TestCase):
	def setUp(self):
		self.widget = Widget("The widget")

class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
	def runTest(self):
		assert self.widget.size() == (50,50), 'incorrect default size'

class WidgetResizeTestCase(SimpleWidgetTestCase):
	def runTest(self):
		self.widget.resize(100,150)
		assert self.widget.size() == (100,150), \
		'wrong size after resize'

๋งŒผ setUp ๋ฉ”†Œ๋“œ๊ฐ€ …ŒŠคŠธค‘ ˜ˆ™ธ๋ฅผ ๋ฐœƒ•  ๊ฒฝšฐ framework๋Š” ด …ŒŠคŠธ— error๋ฅผ ๊ฐ€ง€๊ณ  žˆ๋‹ค๊ณ  ƒ๊ฐ•  ๊ฒƒด๋‹ค. ๊ทธ๋ฆฌ๊ณ  runTest ๋ฉ”†Œ๋“œ๊ฐ€ ‹ค–‰๋˜ง€ •Š„ ๊ฒƒด๋‹ค.

๋‹จˆœžˆ, šฐ๋ฆฌ๋Š” tearDown ๋ฉ”†Œ๋“œ๋ฅผ  œ๊ณต•  ˆ˜ žˆ๋‹ค. runTest๊ฐ€ ‹ค–‰๋˜๊ณ  ๋‚œ ๋’ค˜ ผ„ •ด๊ฒฐ•œ๋‹ค.
~cpp 
import unittest

class SimpleWidgetTestCase (unittest.TestCase):
	def setUp (self):
		self.widget = Widget ("The widget")
	def tearDown (self):
		self.widget.dispose ()
		self.widget = None
๋งŒผ setUp ๋ฉ”†Œ๋“œ ‹ค–‰ด „๊ณต๋˜๋ฉด, tearDown ๋ฉ”†Œ๋“œ๋Š” runTest๊ฐ€ „๊ณต•˜๊•ˆ•˜๊ƒ๊ด€—†ด ˜ธถœ๋  ๊ฒƒด๋‹ค.

ด๋Ÿฌ•œ testing code๋ฅผ œ„•œ ž‘—…™˜๊ฒฝ„ 'fixture' ๋ผ๊ณ  •œ๋‹ค.

6. —ฌ๋Ÿฌ๊ฐœ˜ test method๋ฅผ ฌ•จ•œ TestCase classes


ข…ข…, ๋งŽ€ ž‘€ test case๋“คด ๊ฐ™€ fixture๋ฅผ ‚ฌšฉ•˜๊ฒŒ ๋  ๊ฒƒด๋‹ค. ด๋Ÿฌ•œ ๊ฒฝšฐ, šฐ๋ฆฌ๋Š” DefaultWidgetSizeTestCase ๊ฐ™€ ๋งŽ€ ž‘€ one-method class •ˆ— SimpleWidgetTestCase๋ฅผ „œ๋ธŒด๋ž˜‹•˜๊ฒŒ ๋œ๋‹ค. ด๊‹œ๊ฐ„๋‚ญ๋น„ด๊ณ ,.. --a PyUnit๋Š” ๋” ๋‹จˆœ•œ ๋ฉ”ปค๋‹ˆฆ˜„  œ๊ณต•œ๋‹ค.
~cpp 
import unittest

class WidgetTestCase (unittest.TestCase):
	def setUp (self):
		self.widget = Widget ("The widget")
	def tearDown (self):
		self.widget.dispose ()
		self.widget = None
	def testDefaultSize (self):
		assert self.widget.size() == (50,50), 'incorrect default size'
	def testResize (self):
		self.widget.resize (100,150)
		assert self.wdiget.size() == (100,150), 'wrong size after resize'
—ฌ๊ธฐ—๋Š” runTest ๋ฉ”†Œ๋“œ๊ฐ€ —†๋Š”๋Œ€‹ , ๋‘๊ฐœ˜ ๋‹ค๋ฅธ test ๋ฉ”†Œ๋“œ๋ฅผ ๊ฐ€ง€๊ณ  žˆ๋‹ค. ด๋ž˜Šค ธŠค„Šค๋Š” ด œ ๊ฐ๊ฐ self.widget „ ƒ—•˜๊ณ  ๊ฐ ธŠค„Šค— ๋Œ€•ด ๋”ฐ๋กœ †Œ๋ฉธ๋˜๋ฉด„œ ๊ฐ๊ฐ˜ test method๋ฅผ ‹ค–‰•œ๋‹ค.

ธŠค„Šค๋ฅผ ƒ„• ๋•Œ šฐ๋ฆฌ๋Š” ๊ทธ …ŒŠคŠธ ธŠค„Šค๊ฐ€ ˆ˜–‰•  …ŒŠคŠธ ๋ฉ”†Œ๋“œ๋ฅผ ๊ตฌฒด œผ๋กœ ๋ช…‹œ•ดฃผ–ด•ผ •œ๋‹ค. ด ผ€ constructor— ๋ฉ”†Œ๋“œ ด๋ฆ„„  –ดฃผ๋ฉด ๋œ๋‹ค.

~cpp 
defaultSizeTestCase = WidgetTestCase ("testDefaultSize")
resizeTestCase = WidgetTestCase ("testResize")

7. TestSuite : testcase๋“ค˜ ง‘•ฉฒด

Test case ธŠค„Šค๋“ค€ ๊ทธ๋“คด …ŒŠคŠธ•˜๋ ค๋Š” ๊ฒƒ๋“ค— ๋”ฐ๋ผ •จ๊ป˜ ๊ทธ๋ฃน™”๋œ๋‹ค. PyUnit๋Š” ด๋ฅผ œ„•œ 'Test Suite' ๋ฉ”ปค๋‹ˆฆ˜„  œ๊ณต•œ๋‹ค. Test Suite๋Š” unittest ๋ชจ๋“ˆ˜ TestSuite class๋กœ ‘œ˜„๋œ๋‹ค.
~cpp 
widgetTestSuite = unittest.TestSuite ()
widgetTestSuite.addTest (WidgetTestCase ("testDefaultSize"))
widgetTestSuite.addTest (WidgetTestCase ("testResize"))

๊ฐ๊ฐ˜ …ŒŠคŠธ ˆ˜–‰„ œ„•ด (šฐ๋ฆฌ๋Š” ๋‚˜ค‘— ๋‹ค‹œ ๋ณด๊ฒ ง€๋งŒ), ๊ฐ๊ฐ˜ …ŒŠคŠธ ๋ชจ๋“ˆ„ '˜ธถœ•  ˆ˜ žˆ๋Š”' test suite ๊ฐฒด๋ฅผ  œ๊ณต•˜๋Š” ๊ฒƒด ข‹๋‹ค.
~cpp 
def suite ():
	suite = unittest.TestSuite ()
	suite.addTest (WidgetTestCase ("testDefaultSize"))
	suite.addTest (WidgetTestCase ("testResize"))
	return suite
๋˜๋Š”
~cpp 
class WidgetTestSuite (unittest.TestSuite):
	def __init__(self):
		unittest.TestSuite.__init__(self, map(WdigetTestCase, "testDefaultSize", "testResize")))
unittest ๋ชจ๋“ˆ—๋Š” makeSuite ๋ผ๋Š” Žธ๋ฆฌ•œ •จˆ˜๊ฐ€ žˆ๋‹ค. ด •จˆ˜๋Š” test case class •ˆ˜ ๋ชจ๋“  test case๋ฅผ ฌ•จ•˜๋Š” test suite๋ฅผ ๋งŒ๋“ค–ดค€๋‹ค. (™€šฐ!!)
~cpp 
suite = unittest.makeSuite (WidgetTestCase, 'test')
makeSuite •จˆ˜๋ฅผ ‚ฌšฉ• ๋•Œ testcase๋“ค€ cmp •จˆ˜๋ฅผ ‚ฌšฉ•˜—ฌ †ŒŠธ•œ ˆœ„œ๋˜๋กœ ‹ค–‰๋œ๋‹ค.

8. test suite๋“ค˜ ง‘•ฉ. ๋ชจ๋“  …ŒŠคŠธ๋“ค„ •œ๋ฒˆ—~

ข…ข… testcase๋“ค„ •จ๊ป˜ ๋ฌถ€ suites๋“ค˜ ๊ทธ๋ฃน„ ›• ๋•Œ๊ฐ€ žˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ •จœผ๋กœ„œ •œ๋ฒˆ— ๋ชจ๋“  ‹œŠค…œ˜ test๋ฅผ ˆ˜–‰•  ˆ˜ žˆ๋‹ค. TestSuite๋“ค€ TestSuite — ฌ•จ๋  ˆ˜ žˆ๊ธฐ ๋•Œ๋ฌธ— ๋งคšฐ ๊ฐ„๋‹จ•˜๋‹ค.
~cpp 
suite1 = module1.TheTestSuite ()
suite2 = module2.TheTestSuite ()
alltests = unittest.TestSuite ((suite1, suite2))

9. –ด๋””— …ŒŠคŠธฝ”๋“œ๋ฅผ ๋‘˜๊นŒ?

testcode๋Š” 'widgettests.py' ฒ˜๋Ÿผ ๋”ฐ๋กœ …ŒŠคŠธฝ”๋“œ๋“ค— ๋Œ€•œ ๋ชจ๋“ˆ„ ๋‘๋Š” ๊ฒƒด —ฌ๋Ÿฌ๊ฐ€ง€๋ฉด—„œ žฅ „ ง€๋‹Œ๋‹ค.
  • command line—„œ test module๋ฅผ ๋‹จ๋… œผ๋กœ ‹ค–‰•  ˆ˜ žˆ๋‹ค.
  • ฝ”๋“œ™€ testcode๊ฐ€ ‰ฝ๊ฒŒ ๋ถ„๋ฆฌ๋œ๋‹ค.
  • Šน๋ณ„•œ ดœ —†ด testcode๋ฅผ test๋ฐ›„ code— ๋งžถ”๋ ค๋Š” œ ˜น„ ๋œ ˆ˜ žˆ๋‹ค.
  • …ŒŠคŠธ ๋œ ฝ”๋“œ๋ฅผ refactoring •˜๊ธฐ ๋” šฉด•ด„๋‹ค.
  • …ŒŠคŒ…  „๋žตด ๋ฐ”๋€Œ–ด๋„, source code๋ฅผ ๊ณ น  •„š”๊ฐ€ —†–ด„๋‹ค.

10. Test˜ ‹ค–‰

PyUnit test framework๋Š” …ŒŠคŠธ๋ฅผ ˆ˜–‰•˜๊ธฐ œ„•ด 'TestRunner' ด๋ž˜Šค๋ฅผ ‚ฌšฉ•œ๋‹ค. ๊ฐ€žฅ ผ๋ฐ˜ ธ TestRunner๋Š” TextTestRunnerด๋‹ค.
~cpp 
runner = unittest.TextTestRunner ()
runner.run (widget.TestSuite)
๊ธฐ๋ณธ œผ๋กœ TextTestRunner๋Š” sys.stderr— ถœ๋ ฅ•œ๋‹ค. TextTestrunner ๊ฐ™€ ด๋ž˜Šค๋Š” Python interpreter session๊ณผ ƒ˜ธž‘šฉ•˜๋ฉด„œ test๋“ค„ ‹ค–‰‹œผœ๋ณผ ˆ˜ žˆ๋Š” ดƒ ธ ๋ฐฉ๋ฒ•ด๋‹ค.

11. Test กฐ๊ด๋“ค— ๋Œ€•ด„œ

test ฝ”๋“œ๋Š” ๊ฐ๊ฐ˜ testกฐ๊— ๋งžถฐ ๋ฌธ œ๋ฐœƒ‹œ fail ๋“„ ๋ฐœƒ‹œ‚จ๋‹ค.

11.1. assert

~cpp 
def runTest(self):
	self.assert_(self.widget.size() == (100,100), "size is wrong")

11.2. failif

~cpp 
def runTest(self):
	self.failIf(self.widget.size() <> (100,100))

11.3. fail, failUnless

~cpp 
def runTest(self):
...
	if not hasattr(something, "blah"):
	self.fail("blah missing")
	# or just 'self.fail()'

11.4. assertEqual

~cpp 
def testSomething(self):
	self.widget.resize(100,100)
	self.assertEqual(self.widget.size, (100,100))

11.5. exception

~cpp 
def runTest(self):
	try:
		self.widget.resize(-1,-1)
	except ValueError:
		pass
	else:
		fail("expected a ValueError")


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:24:08
Processing time 0.0239 sec