тесты с фикстурами

19

Click here to load reader

Transcript of тесты с фикстурами

Page 1: тесты с фикстурами

Тесты сфикстурами

Иван Гришаев[email protected]

Page 2: тесты с фикстурами

Проблемамы пишем на Питоне (Руби, ПХП, Js…)язык не сигнализирует об ошибкахNone или Exception?слабая типизациянужно много тестов

Page 3: тесты с фикстурами

ПримерБазовая авторизация:

Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1lusername:passwordдостать юзера

в результате:ошибка разбиения строкошибка декодированияошибка разбиения строк (еще раз)исключение, если нет юзера

Page 4: тесты с фикстурами

xUnitJUnit – дедушка современных тест-системпортирован на все что можнопрошел испытание временемне учитывает особенности целевой платформы

Page 5: тесты с фикстурами

Тесты на ООП – плохосвязывание сущностей, наследование, миксинытесты каскадно отваливаютсянет повторного использования кодаогромные setUp

Page 6: тесты с фикстурами

Где-где падает?@patch("some.module.foo", Mock(...)) @patch("some.module.bar", Mock(...)) @patch("some.module.baz", Mock(...)) @patch("some.module.pip", Mock(...)) class MyTest(TestCase, MyMixin, CacheMixin):

...

@override_settings(VALUE=42) @patch("other.module.func", Mock(...)) def test_ok(self): self.do_stuff() ...

Page 7: тесты с фикстурами

В сетапе, говоришь?def setUp(self): self.entity.user_requests_count = 0 self.entity.user = {} self.bar_user_goods_by_front_mock = Mock(return_value=(True, OTHER_DATA)) self.backend_user_mock = Mock(return_value=(True, BACKEND_MOCK)) self.baz_single = Mock(return_value=(True, TEST_SINGLE)) self.storage_mock = Mock(return_value=(200, STORAGE_DATA_NEW)) self.storage_new_mock = Mock(return_value=(200, FAKE_STORAGE)) self.shop_user_stats_mock = Mock(return_value=(True, TEST_USER_STATS_RESPONSE)) self.shop_mock = Mock(return_value=(True, TEST_LIST_RESPONSE)) self.user_mock = Mock(return_value=(True, TEST_EVENTS_USER_SHOP)) self.list_mock = Mock(return_value=(True, TEST_BAZ)) self.user_goods_mock = Mock(side_effect=lambda user_id, **kwargs: (True, {'goods' self.user_friends_mock = Mock(return_value=(200, [{'id': 1}, {'id': 2}, {'id' self.current_mock = Mock(return_value=(True, TEST_SOME_DATA)) self.test_mock = Mock(return_value=(True, {})) self.price_mock = Mock(return_value=(True, {'data': [TEST_OTHER_DATA]})) self.foo_mock = Mock(return_value=(400, None)) self.some_mock = Mock(return_value=(400, None)) self.user_money_mock = Mock(return_value=(200, TEST_USER_MONEY)) self.foo_some_mock = Mock(return_value=(True, TEST_USER_GOODS)) self.foo_some_goods_mock = Mock(return_value=(True, TEST_USER_GOODS_RESPONSE))

Page 8: тесты с фикстурами

Что такое тест?test = predicate(Environment)

Page 9: тесты с фикстурами

Надо такtest = predicate(env1, env2, ... , envN)

Page 10: тесты с фикстурами

Получаются наборыtest_ok = predicate(env1, env2) test_failture = predicate(env1) test_high_price = predicate(env1, env2, env3)

Page 11: тесты с фикстурами

Фреймворки на фикстурахClojure(script) core.testPyTest

Page 12: тесты с фикстурами

Что такое фикстура?любой объект с тремя стадиями:

инициализацияучастие в исполнении тестаудаление

def test_ok(fixture1, fixture2): ...

f1 = fixture1() f2 = fixture1() test_ok(f1, f2) del f1 del f2

разный срок жизнифункциямодульсеанс

Page 13: тесты с фикстурами

Преимуществатест – это функцияоднозначная зависимость от фикстур:

def test_buy(user, goods, cache, auth) def test_auth_failture(user, auth)

независимость тестовнастоящее переиспользование кода

Page 14: тесты с фикстурами

REST-микросервисФикстура – сервис авторизациине надо мокать, все запросы уходят в localhost

app = Flask(__name__)

@app.route("/user/auth")def endpoint_auth(requrest): return jsonify({ 'user': {'name': 'User Name', 'status': 'active'} })

@pytest.yield_fixture(scope="session") def fix_auth(): from multiprocess import Process p = Process(app.run, "127.0.0.1", 9001, True) p.start() yield app p.terminate()

Page 15: тесты с фикстурами

ИзображенияФикстура для подготовки изображений

@pytest.yield_fixture(scope="functions") def fix_avatar(): path = "~/some/path/avatar.png" avatar = PIL.Image(path) yield avatar os.unlink(path)

Page 16: тесты с фикстурами

КешФикстура для чистого кеша

@pytest.fixture(scope='function') def cache(request): _cache = django_cache _cache.clear() request.addfinalizer(_cache.clear) return _cache

Page 17: тесты с фикстурами

Параметрическиефикстуры

заменяют циклылегко добавить еще один случайсправится ли приложение с аватарой 1x1, 128x1,[email protected](scope="function", params=[(1, 1), (128, 1), (5000, 5000)]) def fix_avatar((w, h)): path = "~/some/path/avatar.png" avatar = PIL.Image(path, (w, h)) ...

Page 18: тесты с фикстурами

Выводыписать и поддерживать тесты стало легчеменьше копипастына борту фреймворка много других фишекслова коллеги, который с давно питоном: "не думал,что Пайтест меня так удивит"

Page 19: тесты с фикстурами

Вопросы?