티스토리 뷰
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 |
출처 : http://blog.naver.com/dudwo567890/130166397540
'프로그래밍 > Python' 카테고리의 다른 글
[Splinter] Testing web applications using Python (0) | 2015.11.20 |
---|---|
[pyhwp] HWP 파일을 다양한 확장자로 변환하기 - 2 (0) | 2015.11.19 |
[pyhwp] HWP 파일을 다양한 확장자로 변환하기 - 1 (1) | 2015.11.18 |
[os.walk] 특정 디렉토리(폴더)의 모든 파일 이름 알아내기 (0) | 2015.11.17 |
[tweepy] Python으로 Twitter Streaming API 사용하기(Test) (0) | 2015.11.05 |
- Total
- Today
- Yesterday
- keylogger
- AMSI
- Kimsuky
- VirusBulletin
- cuckoo-sandbox
- 스피어피싱
- 해킹메일
- Static Analysis Engine
- malware
- 멋쟁이사자처럼 4기
- 악성코드
- Flybits
- Decoding
- 출처 : Do it 안드로이드 프로그래밍
- 한글악성코드
- infostealer
- .wll
- vuln
- us-cert
- 위협정보공유
- idapython
- Yara
- Servey
- Cisco Talos
- CVE-2018-0798
- 비트코인
- koodous
- Bisonal
- MS-Office
- CVE-2018-9375
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |