Максим Щепелин. "Unittesting. Как?"

757 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
757
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
11
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Максим Щепелин. "Unittesting. Как?"

  1. 1. Unit testing. Как? Максим Щепелин Wargaming, Python meetup
  2. 2. Говорим о: • Что такое тесты? • Зачем писать тесты? • Как их писать?
  3. 3. Тесты не панацея • Наличие тестов не означает отсутствие ошибок • Тесты проверяют ровно то, что в них написано • Разработка тестов отнимает время • Тесты нужно поддерживать • Не верьте в coverage report!
  4. 4. Хорошие тесты • Проверяют что код делает что ожидается • Не делает ничего кроме того что ожидается • Полностью покрывают логику • Взаимо исключают друг друга • Создают данные в одном месте
  5. 5. Проверяют что код делает что ожидается def remove_friend(user, friend): user.friends.filter(pk=friend.pk).delete() … class UserTests(TestCase): def setUp(self): self.user = User.objects.create(id=1) self.friend1 = User.objects.create(id=2) self.friend2 = User.objects.create(id=3) self.user.friends.add(self.friend1) self.user.friends.add(self.friend2) def test_user_remove_friend(self): remove_friend(self.user, self.friend1) self.assertNotIn( self.friend1, self.user.friends.all() )
  6. 6. Код не делает ничего, кроме того что ожидается def remove_friend(user, friend): user.friends.all().delete() … class UserTests(TestCase): … def test_user_remove_friend(self): friends_count = self.user.friends.count() remove_friend(self.user, self.friend1) self.assertNotIn( self.friend1, self.user.friends.all() ) self.assertEqual(self.user.friends.count(), friends_count - 1)
  7. 7. Полностью покрывают логику Пример из World of Tanks: изменение роли пользователя в клане А что будет если? • Пользователь не обладает правами • Применить новую роль не возможно • Пользователь пытается сменить роль сам себе • Пользователь вышел из клана • …
  8. 8. Взаимо исключают друг друга def test_response_format(self): result = self.call_api('search', page=0, page_size=2) expected = [{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}] self.assertEqual(result['things'], expected) def test_order_by_name(self): # bad result = self.call_api('search', page=0, page_size=2) expected = [{'id': 2, 'name': 'bar'}, {'id': 1, 'name': 'foo'}] self.assertEqual(result['things'], expected) def test_order_by_name(self): # IMHO good resp = self.call_api('search', page=0, page_size=2) ids_order = [item['id'] for item in resp] self.assertEqual(ids_order, [2, 1])
  9. 9. Создают данные в одном месте def test_actions_history(self): Action.objects.create(user=self.user, action_type='change_name') resp = self.call_api('user_actions', user_id=self.user.pk, limit=10) self.assertResponse( resp, user_id= user.pk, actions=[{'id': 1, 'type': 'change_name', 'date': '2014-04-23T16:50:49.849450'}]) def test_actions_history(self): self.create_history_record(user=self.user, action_type='change_name') ...
  10. 10. Хорошие тесты • Показывают что именно работает не верно • Проверяют логику работы приложения • Легко поддерживать
  11. 11. Workflow в команде • Вместе с новой фичей пишутся тесты на нее • Каждый новый баг воспроизводится тестом • Тесты запускаются перед каждым коммитом
  12. 12. Как тестировать сигналы from users.singals import user_created class UserTests(TestCase): signal_invoked = False def setUp(self): user_created.connect(UserTests.fake_handler) def tearDown(self): user_created.disconnect(UserTests.fake_handler) @staticmethod def fake_handler(): UserTests.signal_invoked = True def test_user_created(self): self.call_api('create_user', name='foo') self.assertEqual(self.signal_invoked, True)
  13. 13. Как тестировать кеш def local_cache(backend): locmem_cache = cache.get_cache( 'django.core.cache.backends.locmem.LocMemCache') locmem_cache.clear() return locmem_cache ... @patch('django.core.cache.get_cache', local_cache) def test_get_user_from_cache(self): with self.assertNumQueries(5): self.call_api('user_info', user_id=self.user.pk) with self.assertNumQueries(0): self.call_api('user_info', user_id=self.user.pk)

×