Presentation is loading. Please wait.

Presentation is loading. Please wait.

Combacsa’s SPARCS Web Seminar. xUnit Framework Python : unittest Other testing tools.

Similar presentations


Presentation on theme: "Combacsa’s SPARCS Web Seminar. xUnit Framework Python : unittest Other testing tools."— Presentation transcript:

1 Combacsa’s SPARCS Web Seminar

2 xUnit Framework Python : unittest Other testing tools

3 Test 개념 복습  Testing 이란  프로그램이 잘 개발되었는지 검사하는 과정  Test Code 란  프로그램이 잘 개발되었는지 검사하는 코드  Test Code 가 있는 상황에서의 Testing 이란  Test Code 를 실행시키는 것을 뜻하겠지 ? ㅋ _ ㅋ

4 Unittest  Unit  “ 단위 ”  따로 떼어놓고 생각할 수 있는 한 단위의 기능  Unittest  프로그램 내 하나의 기능이 제대로 작동되는지 그것만을 검사하는 Test  만일 프로그램의 모든 부분에 대한 Unittest 를 모은다면 프로그램 전체에 대한 Test 가 될지도

5 Unittest 실제로 하는 방법  자유분방한 Test Code 를 작성한다  직접 함수를 호출해서  함수의 결과값을 if 문으로 검사해서  우리가 원하는 값이 아니면 화면에 Error 라고  띄우면 그만이겠지 ?  이미 누군가 만든 Framework 를 갖다 쓴다  쓰는 법만 배우면 간단하다

6 이름있는 Unittest 관련 도구들  Java  JUnit  Python  unittest  PHP  PHPUnit  SimpleTest for PHP  C/C++  CppUnit  CppTest  GoogleTest  Ruby  Test::Unit

7 xUnit Framework  역사  Kent Beck  SmallTalk 언어를 위한 SUnit  Java 언어를 위한 JUnit  계속해서 다른 언어를 위해 번역됨  사실 앞에서 소개한 대부분의 도구들이 xUnit Framework 에 기반하고 있다

8 xUnit Framework Terminology  Test Case  Test 의 가장 작은 단위  하나의 기능이 제대로 작동하는지 검사하는 코 드 일체를 뜻함  Test Fixture  Test 가 일어나기 전에 준비되어야 하는 상황  Test 가 끝난 뒤에 정리되어야 하는 상황의 모음  Test Suite  같은 Fixture 를 공유하는 Test Case 의 모음

9 xUnit Framework Terminology  setUp  Test 가 시행되기 전의 준비 과정  tearDown  Test 가 시행된 이후의 정리 과정  Assertion  Test 하는 동작이 원하는 대로 이뤄졌는지를 검 사하여, 원하지 않는 결과가 나오면 Test 를 중지 시키는 것

10 xUnit Framework 작동구조  Test Suite 실행  Test Case 들 각각에 대하여  setUp 실행  Test Case 내의 모든 문장 실행  중간에 assertion 걸리면 해당 Test Case 는 “ 실패 ”  tearDown 실행  결과 보고

11 xUnit Framework Python : unittest Other testing tools

12 Python unittest  JUnit 의 Python 버전  Python 기본 내장 라이브러리  실제로 써보자.

13 상황 설정  TDD 설명할 때와 마찬가지로 기괴한 예제.  PrimeNumber 라는 클래스를 만들어보자  test 라는 메소드를 갖고 있다  파라메터 : 양의 정수 하나  출력 : 문자열  현재의 시각과  해당 정수가 소수인지 아닌지에 대한 정보

14 어떻게 개발할까 ?  프로그래밍 언어  Python  개발 방법론  약간 느슨한 Test-Driven Development  사용할 Testing Framework 라이브러리  unittest

15 지금 당장 할 일  PrimeNumber 클래스를 테스트할 테스트 코드를 만들어야 한다  그 전에, 테스트 코드의 기본형을 우선 만들 어야 한다  결론 : unittest 모듈을 쓰는 가장 기초적인 뼈대가 되는 코드를 작성하자 !

16 prime_number_test.py 초고 import unittest  시작은 unittest 모듈의 import 부터.

17 prime_number_test.py 초고 import unittest class PrimeNumberTest(unittest.TestCase):  unittest.TestCase 를 상속받은 클래스인 Test Case Class 를 선언한다  클래스 이름은 Test 하고자 하는 클래스의 이름 뒤에 Test 를 붙이는 게 관례적이다  이 클래스가 하나의 Test Suite 가 될 것이다

18 prime_number_test.py 초고 import unittest class PrimeNumberTest(unittest.TestCase): def setUp(self): pass  하나의 Test Suite 에는 같은 Test Fixture 를 공유하는 Test 들이 있다고 했다  Test Fixture 는 setUp 과 tearDown 으로 구성 된다고 했다  일단 아무 일도 안 하는 setUp.

19 prime_number_test.py 초고 import unittest class PrimeNumberTest(unittest.TestCase): def setUp(self): pass def tearDown(self): pass  잊지 마고 tearDown 도 넣어주자

20 prime_number_test.py 초고 def tearDown(self): pass def suite(): return unittest.TestLoader().loadTestsFromTestCase( PrimeNumberTest)  이제 suite 를 하나 만들어야 한다  PrimeNumberTest 로부터 만들면 된다  unittest.TestLoader() 객체가 필요하다  그 객체의 loadTestsFromTestCase 함수를 호출하면 어느새 suite 가 완성된다

21 prime_number_test.py 초고 def suite(): return unittest.TestLoader().loadTestsFromTestCase( PrimeNumberTest) if __name__ == "__main__": unittest.TextTestRunner(verbosity=2).run(suite())  만든 Suite 를 실제로 구동하려면 ?  unittest 모듈의 TextTestRunner 클래스의 객체를 만들어낸다 (verbosity : 시끄러운 정도.)  그 객체의 run 메소드에 suite 를 넘겨주면 됨.

22 prime_number_test.py 초고 import unittest class PrimeNumberTest(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def suite(): return unittest.TestLoader().loadTestsFromTestCase( PrimeNumberTest) if __name__ == "__main__": unittest.TextTestRunner(verbosity=2).run(suite())

23 참고  보통의 Test Suite 코드들은 TextTestRunner 객체의 생성에 대한 부분 ( 맨 아래 2 줄 ) 은 생 략되어 있고, 오직 실질적인 Test Runner 코 드에만 그 내용이 있는 경우가 많다.

24 prime_number_test.py import prime_number … def setUp(self): self.prime_number = prime_number.PrimeNumber() … def testProperPrime(self): self.assertEqual(“It is a Prime number”, self.prime_number.test(2)) …  prime_number 모듈의 이름과  PrimeNumber 객체의 생성방법  그리고 test 라는 이름의 method 정의

25 prime_number_test.py 초고 import prime_number … def setUp(self): self.prime_number = prime_number.PrimeNumber() … # assertEqual 메소드는 2 개의 파라메터가 동일한지 검사한다. def testProperPrime(self): self.assertEqual(“It is a Prime number”, self.prime_number.test(2)) …  메소드 이름이 test 로 시작하는 애들  TestCase 를 구성하는 하나의 test 가 된다  실행 순서는 아무래도 좋다는 가정

26 python prime_number_test.py combacsa@sparcs:~$ python prime_number_test.py Traceback (most recent call last): File "prime_number_test.py", line 2, in import prime_number ImportError: No module named prime_number  문제를 해결하는 가장 쉬운 방법  당연히 prime_number 모듈을 만든다.

27 prime_number.py class PrimeNumber(object): def __init__(self): pass def test(self, x): return "It is a Prime number"  TDD recall)  죄악은 당당히 저지르라고 있는 것임.  Test Case 가 부족해서 만회가 안 되는 것을 탓해 !

28 python prime_number_test.py combacsa@sparcs:~$ python prime_number_test.py testProperPrime (__main__.PrimeNumberTest)... ok ------------------------------------------------------------ Ran 1 test in 0.000s OK  초록 막대를 보았다

29 prime_number_test.py … def testImproperPrime(self): self.assertEqual(“It is not a Prime number”, self.prime_number.test(4)) …  ImproperPrime 에 대한 test 를 추가하자 combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... FAIL testProperPrime (__main__.PrimeNumberTest)... Ok ============================================================ FAIL: testImproperPrime (__main__.PrimeNumberTest) ------------------------------------------------------------ Traceback (most recent call last): File "prime_number_test.py", line 15, in testImproperPrime self.assertEqual("It is not a Prime number", self.prime_number.test(4)) AssertionError: 'It is not a Prime number' != 'It is a Prime number' ------------------------------------------------------------ Ran 2 tests in 0.001s FAILED (failures=1)

30 결과 관찰  코드상엔 ImproperPrime 이 더 뒤인데 …  FAIL 이 뜬다. 빨간 막대에 도착. combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... FAIL testProperPrime (__main__.PrimeNumberTest)... Ok ============================================================ FAIL: testImproperPrime (__main__.PrimeNumberTest) ------------------------------------------------------------ Traceback (most recent call last): File "prime_number_test.py", line 15, in testImproperPrime self.assertEqual("It is not a Prime number", self.prime_number.test(4)) AssertionError: 'It is not a Prime number' != 'It is a Prime number' ------------------------------------------------------------ Ran 2 tests in 0.001s FAILED (failures=1)

31 prime_number.py … def test(self, x): for i in range(2, x): if x % i == 0: return “It is not a Prime number” return “It is a Prime number” … combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... ok testProperPrime (__main__.PrimeNumberTest)... ok ------------------------------------------------------------ ---------- Ran 2 tests in 0.000s OK

32 Mock Object / Stub Code  Mock  하나의 객체가 작동하기 위해 다른 객체가 필요 할 때, 굳이 그 “ 다른 객체 ” 를 사용하지 말고, “ 다 른 객체 ” 가 “Test Case 들 내 ” 에서 보이는 행동만 을 하는 “ 가짜 객체 ” 를 Test Code 내에서 사용할 때 쓰는 객체.  단위 Test 를 진짜 “ 단위 코드만 있어도 작동하는 ” Test 로 만들어줌.  Stub  실제 해당 함수가 반환 가능한 다양한 경우의 수 들 중 Test 에서 쓸 일부분만 리턴해보는 것.

33 Stub code “time” … import unittest import time def stub_time(): return 31536001.1 … def setUp(self): self.time = time.time time.time = stub_time def tearDown(self): time.time = self.time …

34 Stub code “time” … import unittest import time def stub_time(): # time.time() 함수는 실제 컴퓨터의 현재 시각을 return 31536001.1 # 알려주는 함수이다. 그러나 Test Code 는 # 매번 실행되는 시각이 다를 것이기 때문에 time.time() 함수를 그대로 … def setUp(self): # Test Code 에 사용할 수는 없다. 따라서 self.time = time.time # “ 특정한 시각 ” 만을 돌려주는 time.time = stub_time # stub 함수를 만들고, time.time … # 함수를 그거로 대체해버리는 것. def tearDown(self): # test 가 끝난 뒤에는 원래의 time.time = self.time # time.time 함수로 복귀시켜주자. …

35 예제를 좀더 확충해 보자  현재 시각을 출력하는 걸 넣어야지 ! … def testProperPrime(self): self.assertEqual( "It is 1971-01-01 09:00:01.100000 and It is a Prime number", self.prime_number.test(2)) def testImproperPrime(self): self.assertEqual( "It is 1971-01-01 09:00:01.100000 and It is not a Prime number", self.prime_number.test(4)) …

36 combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... FAIL testProperPrime (__main__.PrimeNumberTest)... FAIL ============================================================ FAIL: testImproperPrime (__main__.PrimeNumberTest) ------------------------------------------------------------ Traceback (most recent call last): File "prime_number_test.py", line 20, in testImproperPrime self.assertEqual("It is 1971-01-01 09:00:01.100000 and It is not a Prime number", self.prime_number.test(4)) AssertionError: 'It is 1971-01-01 09:00:01.100000 and It is not a Prime number' != 'It is not a Prime number' ============================================================ FAIL: testProperPrime (__main__.PrimeNumberTest) ------------------------------------------------------------ Traceback (most recent call last): File "prime_number_test.py", line 17, in testProperPrime self.assertEqual("It is 1971-01-01 09:00:01.100000 and It is a Prime number", self.prime_number.test(2)) AssertionError: 'It is 1971-01-01 09:00:01.100000 and It is a Prime number' != 'It is a Prime number' ------------------------------------------------------------ Ran 2 tests in 0.001s FAILED (failures=2)

37 테스트를 통과시켜보자 ! import datetime import time … def test(self, x): for i in range(2, x): if x % i == 0: return "It is " + str(datetime.datetime.fromtimestamp(time.time())) + " and It is not a Prime number" return "It is " + str(datetime.datetime.fromtimestamp(time.time())) + " and It is a Prime number"

38 결과 combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... ok testProperPrime (__main__.PrimeNumberTest)... ok ------------------------------------------------------------ ---------- Ran 2 tests in 0.000s OK

39 특이사항에 대한 대처 … def testWrongNum(self): try: self.prime_number.test(-1) self.fail(“Negative number must not be couraged.”) except ZeroDivisionError: pass  self.fail()  테스트를 일부러 실패시킨다.  의도  함수에게 “ 잘못된 입력 ” 을 넣으면, “ 잘못된 입력 ” 임을 인지하고 에러를 발생시키는지 검사 !

40 결과 combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... ok testProperPrime (__main__.PrimeNumberTest)... ok testWrongNum (__main__.PrimeNumberTest)... FAIL ============================================================ FAIL: testWrongNum (__main__.PrimeNumberTest) ------------------------------------------------------------ Traceback (most recent call last): File "prime_number_test.py", line 25, in testWrongNum self.fail("Negative number must not be couraged.") AssertionError: Negative number must not be couraged. ------------------------------------------------------------ Ran 3 tests in 0.001s FAILED (failures=1)

41 합당하게 대처하는 코드 … return "It is " + str(datetime.datetime.fromtimestamp(time.time())) + " and It is not a Prime number" if x < 0: raise ZeroDivisionError return "It is " + str(datetime.datetime.fromtimestamp(time.time())) + " and It is a Prime number“ …

42 결과 combacsa@sparcs:~$ python prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... ok testProperPrime (__main__.PrimeNumberTest)... ok testWrongNum (__main__.PrimeNumberTest)... ok ------------------------------------------------------------ ---------- Ran 3 tests in 0.001s OK

43 숙제  우리의 prime_number.py 와 prime_number_test.py 는 “1” 에 대해 어떻게 처리할까 ? 1 은 소수가 아니다. 합당한 출력 을 하도록 고쳐 보자.  새로운 Exception 을 Define 하자. 각각 “WrongNumberRangeError”, “NotANumberError” 라고 하자. 이 두 Error 를 리턴하도록 PrimeNumber.test 를 고치자.

44 SUMMARY Unittest 는 프로그램의 특정 기능 하나만을 Test 하는 것을 뜻한다. 대체로 켄트 백에 의해 주창 된 xUnit Framework 를 기반으로 한 Java 의 JUnit 이나 Python unittest 모듈, C++ 의 Google Test 모 듈 등을 통해 구현된다. Test Fixture, Test Case, Test Suite, Test Runner 로 구성된다. Python 사용자들은 unittest, doctest, coverage 등의 모듈을 써보면 좋다.

45 xUnit Framework Python : unittest Other testing tools

46 Java 사용자들이여  Junit  http://www.junit.org http://www.junit.org  어차피 Eclipse / NetBeans 깔면 기본으로 들어있음  Eclipse  http://www.eclipse.org http://www.eclipse.org  Java 쓰는 사람이 Eclipse 안 쓰면 바보라는 소문이 …  그러나 GUI Programming 할 때는 NetBeans 가 더 …  EclEmma  http://www.eclemma.org/ http://www.eclemma.org/  Java 를 위한 Code Coverage 툴

47 Python doctest  주석 자체에 test 를 집어넣어두면 그로부터 test 를 실행하는 모듈  Pros  Test 자체를 해당 함수에 대한 주석으로 삼을 수 있어, Test 도 함수에 대한 소개로 쓰일 수 있다  Cons  Unittest 모듈과 달리 setUp, tearDown 등을 따로 쓰기 어려우며 형식이 Python Interpreter 라 지저 분하다

48 Python coverage  Code Coverage?  한 프로그램에 대한 Test Code 들이 프로그램의 모든 소스코드를 Test 하는지, 아니라면 어느 줄 을 Test 하지 못하는지 검사하는 것  Code Coverage 가 100% 가 아니라면, 작성된 Test 만으로는 프로그램이 정상 작동하는지 보증하 기 어렵다는 것을 뜻한다

49 Coverage 사용 예제  테스트 케이스 하나 지우고 해보자. #def testProperPrime(self): # self.assertEqual("It is 1971-01-01 09:00:01.100000 and It is a Prime number", self.prime_number.test(2)) combacsa@swingfixer:~/cov$ coverage run prime_number_test.py testImproperPrime (__main__.PrimeNumberTest)... ok testWrongNum (__main__.PrimeNumberTest)... ok ------------------------------------------------------------ Ran 2 tests in 0.001s OK combacsa@swingfixer:~/cov$ ls.coverage –alh -rw-r--r-- 1 combacsa combacsa 213 2010-06-09 19:48.coverage

50 Coverage 사용 예제 combacsa@swingfixer:~/cov$ coverage report -m Name Stmts Exec Cover Missing ------------------------------------------------- prime_number 12 11 91% 14 prime_number_test 24 23 95% 25 ------------------------------------------------- TOTAL 36 34 94% combacsa@swingfixer:~/cov$ coverage html combacsa@swingfixer:~/cov$ ls htmlcov/ coverage_html.js jquery-1.3.2.min.js prime_number.html style.css index.html jquery.tablesorter.min.js prime_number_test.html

51

52 Coverage 사용 예제  테스트 케이스 되살려보면 … def testProperPrime(self): self.assertEqual("It is 1971-01-01 09:00:01.100000 and It is a Prime number", self.prime_number.test(2)) combacsa@swingfixer:~/cov$ coverage report -m Name Stmts Exec Cover Missing ------------------------------------------------- prime_number 12 12 100% prime_number_test 26 25 96% 25 ------------------------------------------------- TOTAL 38 37 97%

53 xUnit 이외의 Testing 도구  xUnit 말고도 이런 것도 있음  Test Anything Protocol (TAP)

54 References  Kent Beck, 테스트 주도 개발  김창준, 강규영 역  http://www.javajigi.net/pages/viewpage.actio n?pageId=278 http://www.javajigi.net/pages/viewpage.actio n?pageId=278


Download ppt "Combacsa’s SPARCS Web Seminar. xUnit Framework Python : unittest Other testing tools."

Similar presentations


Ads by Google