티스토리 뷰

Python

Python,module unittest [단위테스트]

hwangyoungjae 2016. 5. 25. 18:41
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

Python에서는 PyUnit이라고도 불리는 unittest모듈에서 단위테스트를 제공한다.

일반적으로 어떤 모듈이나 함수를 작성할때 정상동작여부를 테스트하는 과정을 거치게 된다이러한 테스트 케이스들은 한번 사용하고 버리는 경우가 대부분이다하지만 다음에 코드가 수정되어도 기존에 작성한 테스트들을 수행할수 있게끔 해주는 라이브러리가 unittest이다.

 

>> TestCase <<

기본적으로 unittest모듈은 아래와 같이 간단하게 사용할수 있다.

import unittest

 

def sum(a,b):

    return a+b

 

class ModuleTest1(unittest.TestCase):

    def testsum1(self):

        self.assertEqual(sum(1,2),3)

    def testsum2(self):

        self.assertEqual(sum(1,-1),0)

 

unittest.main()

코드를 보면 unittest모듈을 임포트하고 나서 테스트의 대상이 되는 sum()함수를 정의한다 그 아래에는 테스트를 수행할 클래스를 만드는데반드시 unittest.TestCase클래스를 상속받아야만 한다.

그 다음에는 실제로 테스트결과를 비교할 멤버함수인 testSum1() testSum2()를 구현한다.

마지막으로 unittest.main()을 호출하여 테스트를 수행한다.

 

이렇게 정해진 형식으로 unittest.TestCase클래스를 상속받는 클래스를 만들고 test로 시작하는 멤버 메서드 안에 assert로 시작하는 함수들로 테스트결과를 확인하는 작업을 해야만, unittest.main()이 호출되었을때 제대로 테스트를 수행한다.

또한 멤버 메서드 이름은 test로 시작해야 따로 지정을 하지 않아도 테스트 대상으로 인식한다.

실행 결과는 아래와 같다.

..

----------------------------------------------------------------------

Ran 2 tests in 0.000s

 

OK

실제로는 저렇게 테스트를 빈약하게 하지도 않을 것이고테스트할 대상이 저렇게 간단하지도 않을것이다.

그러나 위와 같이 모듈을 만들때 테스트를 같이 넣는다면모듈모드의 수정이 있을경우에도 기존 기능이 제대로 동작하는지 쉽게 확인할수 있을 것이다.

 

앞의 예제 코드에서 나온 assertEqual()함수는 입력인자로 오는 두값이 동일한지 검사하는 함수이다.

아래는 테스트값을 좀더 쉽게 비교하도록 제공되는 assert관련 함수들중 자주 사용되는 함수들이다.

함수명

설명

assertEqual(first, second, [msg])

first second가 같은지 테스트

같지 않은 경우 테스트가 실패하며 msg를 출력한다.

assertNotEqual(first, second, [msg])

first second가 다른지 테스트

같은 경우 테스트가 실패하며 msg를 출력한다.

assertTrue(expr, [msg])

expr True인지 테스트

False인 경우 테스트가 실패하며 msg를 출력

assertFalse(expr, [msg])

expr False인지 테스트

True인 경우 테스트가 실패하며 msg를 출력

이 외에도 setUp() tearDown()도 자주 쓰이는데, setUp()함수는TestCase클래스의 테스트가 수행되기 전에 테스트 환경을 설정하는 역할을 하며, tearDown()함수는 테스트 수행후 테스트 환경을 정리하는 역할을 한다.

import unittest

 

class ModuleTest2(unittest.TestCase):

    def setUp(self):

        self.bag=[True,True]

    def tearDown(self):

        del self.bag

    def test_true(self):

        for element in self.bag:

            self.assertTrue(element)

 

unittest.main()

실행결과

.

----------------------------------------------------------------------

Ran 1 test in 0.000s

 

OK

여기서는 bag이라는 멤버 변수를 설정해놓고, test_true() 메서드 내에서bag에 들어있는 값들이 True인지 검사하는 작업을 한다.

위의 예제에서 setUp()메서드에서는 초기값 설정을, tearDown()메서드에서는 멤버변수 삭제라는 다소 의미없는 작업을 했지만, test_true()메서드를 비롯하여 다른 테스트에서도 bag이 사용되거나보다 복잡한 환경을 설정/해제할때는 의미 있게 사용될수 있다.

 

아래는 테스트에 실패하게끔 하여 결과를 출려해 보았다.

import unittest

 

class moduletest(unittest.TestCase):

    def test1(self):

        self.assertEqual(3,3) #같은값인지 테스트

    def test2(self):

        self.assertNotEqual(3,3) #다른값인지 테스트

 

unittest.main()

실행결과

.F

======================================================================

FAIL: test2 (__main__.moduletest)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "python.py", line 7, in test2

    self.assertNotEqual(3,3) #다른값인지 테스트

AssertionError: 3 == 3

 

----------------------------------------------------------------------

Ran 2 tests in 0.000s

 

FAILED (failures=1)

첫번째 테스트 케이스는 통과해서 "."이 찍혔지만두번째는 통과못해서 "F"가 출력된걸 알수 있다.

어디서 왜 어긋났는지도 코드의 라인과 같이 결과로 출력이 된다.

 

>> TestSuite <<

테스트슈트(TestSuite)란 테스트케이스나 테스트슈트의 집합을 의미한다.

이번에는 테스트가 여러개인 경우에 대해서 생각해 본다앞에서 예로든 클래스들을 각각 테스트슈트로 지정하고이를 모두 테스트하는 코드를 작성해보겠다.

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import unittest

 

def sum(a,b):

    return a+b

 

class Module1Test(unittest.TestCase):

    def testSum1(self):

        self.assertEqual(sum(1,2),3)

    def testSum2(self):

        self.assertEqual(sum(1,-1),0)

 

class Module2Test(unittest.TestCase):

    def setUp(self):

        self.bag = [True,True]

    def tearDown(self):

        del self.bag

    def test_true(self):

        for element in self.bag:

            self.assertTrue(element)

 

def makeSuite(testcase,tests):

    return unittest.TestSuite(map(testcase,tests)) #testcase를 이용해서 testsuite생성

 

if __name__=='__main__':

    suite1=makeSuite(Module1Test,['testSum1','testSum2'])

    suite2=makeSuite(Module2Test,['test_true'])

   

    allsuites=unittest.TestSuite([suite1,suite2]) #모든 testsuite를 묶음

    unittest.TextTestRunner(verbosity=2).run(allsuites) #모든 test suite를 수행

이 코드에서 핵심은 25라인의 TestSuite클래스를 생성하는 부분이다.

원래는 unittest.TestSuite()를 이용하여 TestSuite클래스를 생성해야 하는데 중복되는 부분이므로 따로 함수로 정리했다.

22라인과 28라인에서 볼수 있듯이 TestSuite클래스는 TestCase TestSuite클래스들로 이루어지며, unittest.TestSuite클래스의 생성자에 TestCase들을 리스트로 입력해서 간단하게 만들수도 있지만여기서는 각각 함수를 지정하고 있다.

 

마지막으로 29라인에서는 이렇게 만들어진 TestSuite TextTestRunner클래스의 run()메서드로 실행한다

(일반적으로 TextTestRunner와 같은 클래스들을 'Test runner'라고 한다.)

verbosity는 아래 실행결과와 같이 test결과에서 출력 레벨을 조정하는 인자이다.

testSum1 (__main__.Module1Test) ... ok

testSum2 (__main__.Module1Test) ... ok

test_true (__main__.Module2Test) ... ok

 

----------------------------------------------------------------------

Ran 3 tests in 0.000s

 

OK

 

>> FunctionTestCase <<

이번에는 기존에 작성된 함수를 이용해서 TestCase를 만드는 방법을 알아보도록 하겠다.

이러한 기능은 unittest.FunctionTestCase클래스를 이용하면 쉽게 작성할수 있다.

또한 기존 메서드중에서 setUp() tearDown()에 매핑할수도 있다.

 

아래 예제코드를 보면 기존의 간단한 함수들(test, init, fin)이 있을 경우어떻게 TestCase가 생성되고 실행될수 있는지 알수 있다.

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

import unittest

 

def test():

    print('\tthis function is to test old functions')

    assert 1 is not None

   

def init():

    print('\n\tinitialized')

 

def fin():

    print('\tfinalized')

 

if __name__ == '__main__':

    testcase=unittest.FunctionTestCase(test,setUp=init, tearDown=fin)

    suite=unittest.TestSuite([testcase])

    unittest.TextTestRunner(verbosity=2).run(suite)

05라인을 보면 기존의 test()함수내의 assert문에서 발생하는 예외를 잡아서 테스트의 성공여부를 확인하는 것을 알수 있으며, 14라인에서 FunctionTestCase클래스 생성시 setUp으로 init()함수를, tearDown으로 fin()함수를 할당하는 것을 볼수 있다.

다음과 같이 init, test, fin이 정상적으로 수행되는것을 확인할수 있다.

unittest.case.FunctionTestCase (test) ...

        initialized

        this function is to test old functions

        finalized

ok

 

----------------------------------------------------------------------

Ran 1 test in 0.000s

 

OK

 

 

참조 : 빠르게 활용하는 파이썬프로그래밍

'Python' 카테고리의 다른 글

Python,module doctest  (0) 2016.05.25
Python,module pydoc [도움말]  (0) 2016.05.25
Python, 웹 서버 만들기  (0) 2016.05.25
Python, 네이버검색 OpenAPI이용하기  (0) 2016.05.24
Python,module socket [소켓통신]  (0) 2016.05.24
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함