Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PyCon Russia 2018 — Unit Testing
Search
Vadim Pushtaev
July 23, 2018
Programming
440
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PyCon Russia 2018 — Unit Testing
Vadim Pushtaev
July 23, 2018
More Decks by Vadim Pushtaev
See All by Vadim Pushtaev
Perl course (5), testing
vadimpushtaev
0
130
MR::Go::Admin::Test
vadimpushtaev
0
100
Perl course (4), testing
vadimpushtaev
0
130
Perl course (4), db
vadimpushtaev
0
240
Perl course (4), oop
vadimpushtaev
1
200
Perl course (4), mod
vadimpushtaev
0
210
Perl course (3), testing
vadimpushtaev
0
110
Perl course (3), db
vadimpushtaev
0
98
Perl course (3), oop
vadimpushtaev
0
120
Other Decks in Programming
See All in Programming
Next.js: The final boss of Web Performance
guaca
0
260
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
350
sbt 2.0: takeoff
eed3si9n
0
160
外から家のPCの電源入れたい!をPHPで解決する
kawashimo0
1
130
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
380
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
430
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
300
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
310
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
270
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
220
contenteditable と日本語入力に向き合う
colorful12
0
200
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
580
Building an army of robots
kneath
307
47k
ラッコキーワード サービス紹介資料
rakko
1
5.3M
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Deep Space Network (abreviated)
tonyrice
0
370
HDC tutorial
michielstock
2
960
The Limits of Empathy - UXLibs8
cassininazir
2
720
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
330
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
WCS-LA-2024
lcolladotor
0
890
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
570
Transcript
UNIT TESTING Вадим Пуштаев
Принципы Реализация 02/34 Что мы хотим? План доклада
03/34 Что мы хотим?
Регрессия 04/34
Влияние на архитектуру 05/34
Понимание 06/34
Отладка 07/34
Комфорт 08/34
Принципы
f: X Y Test the interface, not the implemen- tation?
X Y 10/34
Test the interface, not the implemen- tation? Y f: X
Y X 11/34
Test first 12/34
Unit testing ≠ testing 13/34
14/34 unittest xUnit – SUnit – JUnit – RUnit →
RSpec – ...
unittest Meszaros, Gerard (2007) xUnit Test Patterns 15/34
Этапы теста Arrange Act Assert Setup Exercise Verify Teardown 16/34
Setup Память Файловая система База данных … 17/34
Гибкие параметры def create(dt=None): if dt is None: dt =
datetime.now() def download(requests_lib=None): if requests_lib is None: requests_lib = requests class Downloader: def __init__(self, config, logger): self._config = config self._logger = logger 18/34
19/34 mock from unittest import mock requests_lib = mock.MagicMock() requests_lib.get.return_value.status_code
= 404 @mock.patch('that.module.requests') def test_download(self, requests_lib): requests_lib.get.return_value.status_code = 404
20/34 Файловая система import tempfile� with tempfile.TemporaryFile() as f: f.write(b'Test
data\n') output = io.StringIO() output.write('Test data\n')
База данных Поддельная база 21/34
База данных Поддельная база SQLite 22/34
База данных Поддельная база SQLite Настоящая база 23/34
Данные в базе Копия реальной базы 24/34
Данные в базе Копия реальной базы Слепок реальной базы 25/34
Данные в базе Копия реальной базы Слепок реальной базы Вручную
подготовленные данные 26/34
Данные в базе Копия реальной базы Слепок реальной базы Вручную
подготовленные данные Пустая база 27/34
Данные в базе Копия реальной базы Слепок реальной базы Вручную
подготовленные данные Пустая база Фабрики 28/34
factory_boy import factory from . import models class UserFactory(factory.django.DjangoModelFactory): class
Meta: model = models.User first_name = factory.Sequence( lambda n: 'User #{}'.format(n) ) group = factory.SubFactory(GroupFactory) 29/34 user = UserFactory()
Транзакции setUp = BEGIN tearDown = ROLLBACK self.break_db() 30/34
def setUp(self): super(BaseTestCase, self).setUp() self._patchers = { 'etcd': patch('common.utils.etcd.Etcd.write'), 'celery':
patch('celery.current_app.send_task'), } self._patchers['etcd'].return_value = None self._patchers['celery'].return_value = True for patcher in self._patchers.values(): patcher.start() � Patchers 31/34
def assertDirExists(self, dir_path): self.assertTrue(os.path.isdir(dir_path)) def assertNotFileExists(self, file_path): self.assertFalse(os.path.exists(file_path)) def assertFileContent(self,
content, path): with open(path, 'rb') as fh: self.assertEqual(content, fh.read()) Custom asserts 32/34
@BaseTestCase.cases( ( 'dst', pytz.timezone('Europe/Moscow'), DT.utc(2011, 3, 27, 6, 12, 23),
# 10:12:23 (MSD) datetime.date(2011, 3, 27), ), ( 'no_dst', pytz.timezone('Europe/Moscow'), DT.utc(2016, 2, 7, 23, 43, 12), # 02:43:12 (MSK) datetime.date(2016, 2, 8), ), ) def test_date_of_time(self, timezone, dt, date): self.assertEqual(DT.date_of_time(dt, timezone), date) 33/34 Таблицы результатов https://bit.ly/2NvZdUT
Итого
Спасибо! @pushtaev @pythonetc Пуштаев Вадим
Тестирование приватного метода?
def count_german_letters(self): return len([ x for x in self._string if
self._is_german_letter(x) ]) def delete_german_letters(self): return ''.join( x for x in self._string if not self._is_german_letter(x) ) def _is_german_letter(self, c): return c in string.ascii_lowercase or c in 'ÄäÖöÜü ß'