2019년 12월 8일 일요일

python testcase unittest 사용법


기본 예제

unittest 모듈을 사용합니다.
assertEqual 이라는것은 양쪽의 값이 같은 경우는 pass되는 함수 입니다. unittest를 실행하는건 unittest.main()을 호출 하면서 시작하며, test를 원하는 함수는 unittest.TestCase 를 상속하여 클래스를 만듭니다. 그리고 내부 메소드 이름이 test로 시작하는 함수들이 실행이 되는데 내부적을 순서가 있습니다. test로 시작하지 않는 메소드는 실행이 되지 않습니다.
아래 예제는 3개의 testcase 함수가 있고 3가지 모두 끝나면 Ran 3가 출력됩니다.
여기에서는 파일의 이름을 testcase.py로 만들었습니다.

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()

실행화면
C:\Users\USER\Documents\python\testcase>python testcase.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

-v 옵션은 더 많은 로그를 제공합니다. 
실행 되는 순서를 보면 소스코드의 순서와 일치 하지 않습니다. 함수의 순서를 바꾸어 봐도 변경되지 않습니다. 알파벳 순으로 실행되는것 처럼 보입니다. (문서로 확인된 내용은 아닙니다.)
C:\Users\USER\Documents\python\testcase>python testcase.py -v
test_isupper (__main__.TestStringMethods) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK


테스트의 특정 모듈 특정 함수만 실행이 가능합니다. -m unittest 를 이용
C:\Users\USER\Documents\python\testcase>python -m unittest testcase
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

C:\Users\USER\Documents\python\testcase>python -m unittest -v testcase
test_isupper (testcase.TestStringMethods) ... ok
test_split (testcase.TestStringMethods) ... ok
test_upper (testcase.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK

C:\Users\USER\Documents\python\testcase>python -m unittest -v testcase.TestStringMethods
test_isupper (testcase.TestStringMethods) ... ok
test_split (testcase.TestStringMethods) ... ok
test_upper (testcase.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK

C:\Users\USER\Documents\python\testcase>python -m unittest -v testcase.TestStringMethods.test_isupper
test_isupper (testcase.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK


Test 시작과 종료시 동작 추가(Setup과 teardown)


import unittest

class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("setup")

    def tearDown(self):
        print("tearDown")

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()
setup 과 teardown을 넣었습니다. 이것은 각각의 test의 시작과 종료시에 호출이 됩니다. __init__과 동작이 다릅니다. init은 instance과 생길때 한번만 호출되게 됩니다.
결과를 보시죠

C:\Users\USER\Documents\python\testcase>python testcase.py
setup
tearDown
.setup
tearDown
.setup
tearDown
.
----------------------------------------------------------------------
Ran 3 tests in 0.004s

OK
전체적으로 3번씩 각각 호출되었음을 알 수 있습니다.

-v 옵션으로 실행시켜 보면 좀 더 확실합니다.
C:\Users\USER\Documents\python\testcase>python testcase.py -v
test_isupper (__main__.TestStringMethods) ... setup
tearDown
ok
test_split (__main__.TestStringMethods) ... setup
tearDown
ok
test_upper (__main__.TestStringMethods) ... setup
tearDown
ok

----------------------------------------------------------------------
Ran 3 tests in 0.004s

OK

에러 유발시

코드를 에러가 발생하도록 변경해봤습니다.

import unittest

class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("setup")

    def tearDown(self):
        print("tearDown")

    def test_upper(self):
        print("test_upper start")
        self.assertEqual('foo'.upper(), 'FOO')
        print("test_upper end")

    def test_isupper(self):
        print("test_isupper start")
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())
        print("test_isupper end")

    def test_split(self):
        print("test_split start")
        s = 'hello world'
        self.assertEqual(s.split(), ['hell', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)
        print("test_split end")

if __name__ == '__main__':
    unittest.main()

테스트를 해보면 아래와 같이 정신이 좀 없습니다. 사유는 test case에서 출력하는 print문과 섞여서 그렇습니다. 에러가 발생하더라도 다른 test를 계속해서 진행하기 때문입니다.

C:\Users\USER\Documents\python\testcase>python testcase.py
setup
test_isupper start
test_isupper end
tearDown
.setup
test_split start
tearDown
Fsetup
test_upper start
test_upper end
tearDown
.
======================================================================
FAIL: test_split (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testcase.py", line 24, in test_split
    self.assertEqual(s.split(), ['hell', 'world'])
AssertionError: Lists differ: ['hello', 'world'] != ['hell', 'world']

First differing element 0:
'hello'
'hell'

- ['hello', 'world']
?       -

+ ['hell', 'world']

----------------------------------------------------------------------
Ran 3 tests in 0.003s

FAILED (failures=1)

-v 옵션을 실행해보면 좀더 확실합니다.

C:\Users\USER\Documents\python\testcase>python testcase.py -v
test_isupper (__main__.TestStringMethods) ... setup
test_isupper start
test_isupper end
tearDown
ok
test_split (__main__.TestStringMethods) ... setup
test_split start
tearDown
FAIL
test_upper (__main__.TestStringMethods) ... setup
test_upper start
test_upper end
tearDown
ok

======================================================================
FAIL: test_split (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testcase.py", line 24, in test_split
    self.assertEqual(s.split(), ['hell', 'world'])
AssertionError: Lists differ: ['hello', 'world'] != ['hell', 'world']

First differing element 0:
'hello'
'hell'

- ['hello', 'world']
?       -

+ ['hell', 'world']

----------------------------------------------------------------------
Ran 3 tests in 0.007s

FAILED (failures=1)

test_split 수행중 test fail이 발생하여 이후 테스트가 중단되어 end까지 도달하지 않고 다음 테스트를 진행했네요. 이때 필요한 옵션이 -f 옵션입니다.
-f, --failfast
Stop the test run on the first error or failure.
에러가 발생하면 즉각 멈추도록 합니다. 한결 보기가 쉽습니다.

C:\Users\USER\Documents\python\testcase>python testcase.py -v -f
test_isupper (__main__.TestStringMethods) ... setup
test_isupper start
test_isupper end
tearDown
ok
test_split (__main__.TestStringMethods) ... setup
test_split start
tearDown
FAIL

======================================================================
FAIL: test_split (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "testcase.py", line 24, in test_split
    self.assertEqual(s.split(), ['hell', 'world'])
AssertionError: Lists differ: ['hello', 'world'] != ['hell', 'world']

First differing element 0:
'hello'
'hell'

- ['hello', 'world']
?       -

+ ['hell', 'world']

----------------------------------------------------------------------
Ran 2 tests in 0.003s

FAILED (failures=1)


언어 : Python 3
참고 site : https://docs.python.org/3/library/unittest.html





















댓글 없음:

댓글 쓰기