28
Python UnitTest

Python Unittest

  • Upload
    -

  • View
    401

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Python Unittest

Python UnitTest

Page 2: Python Unittest

무엇을 테스트 해야 하지? == 무엇을 만들어야 하는지 모름

Page 3: Python Unittest

Test passes테스트를 통과 할 수 있게 최소

한의 프로그래밍

실패하는 테스트를 작성

Test fails Refactor코드 의존성 제거 및 품질 향상

Page 4: Python Unittest

Basic Exampleimport randomimport unittestclass PizzaTest(unittest.TestCase): def setUp(self): self.seq = list(range(10)) def test_shuffle(self): random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, list(range(10))) #리스트를 변경해야하는데 튜플은 변경이 안되어 TypeError 발생 self.assertRaises(TypeError, random.shuffle, (1,2,3)) def test_choice(self): element = random.choice(self.seq) self.assertTrue(element in self.seq) def test_sample(self): with self.assertRaises(ValueError): #첫번째 파라미터가 가진 리스트 갯수 보다 많은 수를 입력하여 ValueError가 발생함 random.sample(self.seq, 20) for element in random.sample(self.seq, 5): self.assertTrue(element in self.seq)

테스트 함수 실행 될때마다 먼저 실행되는 준비 함수

unittest.TestCase를 상속받아야 함

테스트 할 함수의 이름이test로 시작해야 함

$ python3 -m unittest tests.py

Page 5: Python Unittest

Test Discovery

python -m unittest discover -s project_directory -p '*_test.py'

테스트를 찾는 패턴을 커스터마이징 할 수 있다.

-v, --verboseVerbose output

-s, --start-directory directoryDirectory to start discovery (. default)

-p, --pattern patternPattern to match test files (test*.py default)

-t, --top-level-directory directory

Page 6: Python Unittest

Test Suite

내가 원하는 대로 테스트 구성 하기

def suite(): suite = unittest.TestSuite() suite.addTest(PizzaTest('test_choice')) # suite.addTest(PizzaTest('test_sample')) return suiteif __name__ == '__main__': unittest.TextTestRunner().run(suite())

Page 7: Python Unittest

Test Skip

@unittest.skip("demonstrating skipping") def test_nothing(self): self.fail("shouldn't happen") @unittest.skipIf(mylib.__version__ < (1, 3), "not supported in this library version") def test_format(self): # Tests that work for only a certain version of the library. [email protected](sys.platform.startswith("win"), "requires Windows") def test_windows_support(self): # windows specific testing code pass

Page 8: Python Unittest

Python3.4 Assertions

Page 9: Python Unittest

assertEqual(a, b)

a와 b가 같으면 테스트 성공 그렇지 않으면 실패

Page 10: Python Unittest

assertNotEqual(a, b)

a와 b가 같지 않으면 테스트 성공

Page 11: Python Unittest

assertTrue(x), assertFalse(x)

함수 의미와 동일하게 True이거나 False이면 성공

Page 12: Python Unittest

assertIs(a, b), assertIsNot(a, b)

a와 b가 같은 오브젝트 이면 성공하거나 아니면 성공

Page 13: Python Unittest

assertIsNone(x), assertIsNotNone(x)

x가 None 이면 성공이거나 None이 아니면 성공

Page 14: Python Unittest

assertIn(a, b), assertNotIn(a, b)

a가 b에 속해 있으면 성공, a가 b에 속하지 성공

Page 15: Python Unittest

assertIsInstance(a, b), assertNotIsInstance(a, b)

a = objectb= class

a가 b의 인스턴스이면 성공, 아니면 성공

Page 16: Python Unittest

assertRaises(exc, fun, *args, **kwds)

def order(): raise Exception

다양한 Exception을 테스트 할 수 있다

def test_order(self): with self.assertRaises(Exception): order()

Page 17: Python Unittest

assertRaisesRegex(exc, r, fun, *args, **kwds)

Exception 메세지에 정규식이 매치가 되면 성공

def test_exception_message_regex(self): self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')

Page 18: Python Unittest

더 있지만 생략

https://docs.python.org/3.4/library/unittest.html#unittest.TestCase.assertAlmostEqual

Page 19: Python Unittest

Django에는 assertion이 더 있음

https://docs.djangoproject.com/en/dev/topics/testing/tools/#assertions

Page 20: Python Unittest

Mock실제 어플리케이션 객체를 특정한 방식으로 흉내 내는 객체

Page 21: Python Unittest

3을 리턴하는 모의 객체 만들어 보기

from unittest.mock import MagicMockclass A(object): def test(self): passclass AuthTest(TestCase): def setUp(self): pass def test_mock(self): inst = A() inst.method = MagicMock(return_value=3) self.assertEqual(inst.method(1), 3) inst.method.assert_called_with(1)

3을 리턴하도록 목 객체 생성

정말 3을 리턴하는지테스트

mock 객체가 호출 되었는지 확인

Page 22: Python Unittest

Raising an exception when a mock is called

def test_side_effect(self): mock = Mock(side_effect=KeyError('Foo')) self.assertRaises(KeyError, mock)

Page 23: Python Unittest

patch

mock.patch를 사용하면 외부 라이브러리의 행위를 바꿀 수 있다.

Page 24: Python Unittest

Fake clientfrom django.test import Clientfrom unittest.mock import MagicMock, Mock, patchdef get_fake_request(status_code, content): m = Mock() m.status_code = status_code m.content = content def fake_get(url, *args, **kwargs): return m return fake_getclass MockTest(TestCase): @patch('django.test.Client.get', get_fake_request(200, 'Fake')) def test_request(self): res = Client.get('http://fake.com') self.assertEqual(res.status_code, 200)

Page 25: Python Unittest

Django UnitTest

Page 26: Python Unittest

Request test

def test_test_view(self): c = Client() res = c.get('/test_view/', {}) e = {'result': 1} self.assertJSONEqual(res.content.decode('utf-8'), json.dumps(e))

post, head, put, patch, delete, trace

Page 27: Python Unittest

login_required view 라면?

@login_requireddef auth_view(request): return HttpResponse(status=200)

def test_login_required_view(self): client = Client() res = client.login(username='debug', password='debug') res = client.get('/auth_view/') self.assertEqual(res.status_code, 200)

Client.login 을 호출하여 로그인을 하면 됨

Page 28: Python Unittest

Rainist, For Making Better Decision

http://www.rainist.com

최명규