Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Тесты с
фикстурами
Иван Гришаев
ivan@grishaev.me
Проблема
мы пишем на Питоне (Руби, ПХП, Js…)
язык не сигнализирует об ошибках
None или Exception?
слабая типизация
нужно м...
Пример
Базовая авторизация:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
username:password
достать юзера
в результате:
ош...
xUnit
JUnit – дедушка современных тест-систем
портирован на все что можно
прошел испытание временем
не учитывает особеннос...
Тесты на ООП – плохо
связывание сущностей, наследование, миксины
тесты каскадно отваливаются
нет повторного использования ...
Где-где падает?
@patch("some.module.foo", Mock(...))
@patch("some.module.bar", Mock(...))
@patch("some.module.baz", Mock(....
В сетапе, говоришь?
def setUp(self):
self.entity.user_requests_count = 0
self.entity.user = {}
self.bar_user_goods_by_fron...
Что такое тест?
test = predicate(Environment)
Надо так
test = predicate(env1, env2, ... , envN)
Получаются наборы
test_ok = predicate(env1, env2)
test_failture = predicate(env1)
test_high_price = predicate(env1, env2, ...
Фреймворки на фикстурах
Clojure(script) core.test
PyTest
Что такое фикстура?
любой объект с тремя стадиями:
инициализация
участие в исполнении теста
удаление
def test_ok(fixture1,...
Преимущества
тест – это функция
однозначная зависимость от фикстур:
def test_buy(user, goods, cache, auth)
def test_auth_f...
REST-микросервис
Фикстура – сервис авторизации
не надо мокать, все запросы уходят в localhost
app = Flask(__name__)
@app.r...
Изображения
Фикстура для подготовки изображений
@pytest.yield_fixture(scope="functions")
def fix_avatar():
path = "~/some/...
Кеш
Фикстура для чистого кеша
@pytest.fixture(scope='function')
def cache(request):
_cache = django_cache
_cache.clear()
r...
Параметрические
фикстуры
заменяют циклы
легко добавить еще один случай
справится ли приложение с аватарой 1x1, 128x1,
5000...
Выводы
писать и поддерживать тесты стало легче
меньше копипасты
на борту фреймворка много других фишек
слова коллеги, кото...
Вопросы?
Upcoming SlideShare
Loading in …5
×

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

https://youtu.be/UCVJS6kETk8

  • Be the first to comment

  • Be the first to like this

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

  1. 1. Тесты с фикстурами Иван Гришаев ivan@grishaev.me
  2. 2. Проблема мы пишем на Питоне (Руби, ПХП, Js…) язык не сигнализирует об ошибках None или Exception? слабая типизация нужно много тестов
  3. 3. Пример Базовая авторизация: Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l username:password достать юзера в результате: ошибка разбиения строк ошибка декодирования ошибка разбиения строк (еще раз) исключение, если нет юзера
  4. 4. xUnit JUnit – дедушка современных тест-систем портирован на все что можно прошел испытание временем не учитывает особенности целевой платформы
  5. 5. Тесты на ООП – плохо связывание сущностей, наследование, миксины тесты каскадно отваливаются нет повторного использования кода огромные setUp
  6. 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() ...
  7. 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, {'go 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)
  8. 8. Что такое тест? test = predicate(Environment)
  9. 9. Надо так test = predicate(env1, env2, ... , envN)
  10. 10. Получаются наборы test_ok = predicate(env1, env2) test_failture = predicate(env1) test_high_price = predicate(env1, env2, env3)
  11. 11. Фреймворки на фикстурах Clojure(script) core.test PyTest
  12. 12. Что такое фикстура? любой объект с тремя стадиями: инициализация участие в исполнении теста удаление def test_ok(fixture1, fixture2): ... f1 = fixture1() f2 = fixture1() test_ok(f1, f2) del f1 del f2 разный срок жизни функция модуль сеанс
  13. 13. Преимущества тест – это функция однозначная зависимость от фикстур: def test_buy(user, goods, cache, auth) def test_auth_failture(user, auth) независимость тестов настоящее переиспользование кода
  14. 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()
  15. 15. Изображения Фикстура для подготовки изображений @pytest.yield_fixture(scope="functions") def fix_avatar(): path = "~/some/path/avatar.png" avatar = PIL.Image(path) yield avatar os.unlink(path)
  16. 16. Кеш Фикстура для чистого кеша @pytest.fixture(scope='function') def cache(request): _cache = django_cache _cache.clear() request.addfinalizer(_cache.clear) return _cache
  17. 17. Параметрические фикстуры заменяют циклы легко добавить еще один случай справится ли приложение с аватарой 1x1, 128x1, 5000x5000? @pytest.fixture(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)) ...
  18. 18. Выводы писать и поддерживать тесты стало легче меньше копипасты на борту фреймворка много других фишек слова коллеги, который с давно питоном: "не думал, что Пайтест меня так удивит"
  19. 19. Вопросы?

×