Укольчик webdriver-а в тест (Inject webdriver in a test)

Изучая язык Python и под впечатлением от
Selenium For Pythonistas, в особенности вот этого момента logged as admin

Решил пересмотреть подход к тестам и сейчас тесты (которых пока не очень много), выглядят так:

class MyTest(MyBaseTestCase):

    def test_pure_api(self):
        something = api.create_something(["nothing", "anything"])
        assert something
        assert "nothing" in something.collection
        assert "anything" in something.collection

    @with_gui()
    def test_mixing_pre_api(self, gui):
        something = api.create_something(["nif-nif", "naf-naf", "nuf-nuf"])
        gui.navigate_to(something)
        assert gui.splinter.is_text_present('nif-nif')
        assert gui.splinter.is_text_present('naf-naf')
        assert gui.splinter.is_text_present('nuf-nuf')

    @with_gui()
    def test_mixin_post_api(self, gui):
        landing_page = gui.to_landing_page()
        something_page = landing_page.create_something(["tom","jerry"]) #page method, returns new page in chain
        #Test with Splinter
        assert gui.splinter.is_text_present('tom')
        assert gui.splinter.is_text_present('jerry')
        #OR Test with page object
        assert something_page.nasty_control.has_text("tom")
        assert something_page.nasty_control.has_text("jerry")

        #ensure is what we see is not only a "picture"
        id, parent_id = something_page.get_ids() #this is quite challenging sometime to provide a loop-back
        something = api.get_something(id, parent_id)
        assert something
        assert "tom" in something.collection
        assert "jerry" in something.collection

За кадром.

  • Оба гуи теста могут использовать один броузер, (можно распараллелить, и каждый тест, находясь в разных потоках будет получать свой webdriver) - с подпилами по большей части взято отсюда, нужно для ускарения тестов

  • with_gui: берет на себя:

    • получить контекст от класса
    • авторизоваться в api
    • “авторизовать browser” (в моем случае поставить нужные куки, пришедшие от api)
    • подготовить Page Factory (чтобы в контексте был один и тот же броузер)
    • обвернуть splinter этим классом (мне удобней использовать сплинтер если локаторы очень хитрые или единоразовые, сохраняет page-ы не большими, не перегужает одноразовыми вещами)
    • как декоратор, передать все это в переменную gui
    • skip тесты, если webdriver отключен (api тестов больше, и они быстрее, как быстрый прогон, не всегда ui нужен)

Есть планы пошарить код, но интересно ли?
Почему-то не кажется чем-то совсем новым, кто знает где такие велосипеды? Может не Python?

1 лайк

Код интересен, покажи, если не секрет. Всегда интересно подсмотреть как у кого реализовано :slight_smile:

Сам я проектировал не один фреймворк тестирования и последовательно их улучшая, пришёл к простым на первый взгляд, но к сожалению не очевидным изначально вещам. Как то:

  1. Код теста должен быть простым, читаемым и кратким
  2. Тест и фреймворк - раздельные иерархии классов (нельзя тест наследовать от фреймворка. Экземпляр фреймворка должен создаваться в (базовом) классе теста)
  3. Нужно предусмотреть возможность работы из теста с различными интерфейсами AUT (application under test): UI, CLI, DB, API, etc.
  4. Нужно предусмотреть возможность работы из теста с несколькими экземплярами AUT (например, для автоматического тестирования миграции данных или апгрейда)
  5. Нужно предусмотреть возможность работы из теста с несколькими различными AUT: для тестирования интеграции

Это фичи, в соответствии с которыми строится базовая архитектура фреймворка. Ну а работа с различными интерфейсами имеет свою детализацию архитектуры и т.д.

Важно понимать так же, что далеко не всем фреймворкам нужны все эти фичи. Нужно строить архитектуру, исходя из потребностей тестирования конкретного набора AUT

1 лайк

Конечно надо зашарить код.Я думаю, будет полезно посмотреть для других, как можно из разных кусок разных фреймворков реализовать задачу под себя. Это тоже ценный опыт. Потому что кода в наше время на GitHub хватает, надо просто научиться его использовать в своих целях.

Я, например, тоже сейчас делаю проект в котором, много переиспользую код из уже существующих python библиотек для Robot Framework, чтобы ускорить написание автоматизации.

Да и другим также я думаю, будет интересно посмотреть на такую штуку как декоратор и его реализацию.

Ну это зависит от того, что ты хочешь далеко в будущем сделать. По одному тесту тяжело сказать, но перечень python фреймворков для автоматизации я указывал здесь, посмотри может что-то и уже и придумано

Кстати, ты unittest используешь или nose или py.test?

Ок, тогда репо-экзампл сделаю, если появится время.
На скорую руку: Show for http://automated-testing.info/t/ukolchik-webdriver-a-v-test-inject-webdriver-in-a-test/4247/3 · GitHub

Это пока для меня сложный вопрос. В основе везде лежит unittest.
Привязка под nose только в attr, именно nose запускает под регрессией, имено он отвечает за распараллеливание.
Локально из под ide, я ранаю используя py.test, в первую очередь из-за удобства assert hook

Если, посоветуете что по поводу распараллеливания, то буду благодарен. Тесты сейчас придерживаемся принципа (по некоторым причинам хотелось бы совместимости с Python 2.7.x и 3.x):

  • порядок независим
  • из-за “тяжелости” прогрева и возможных side-effecot-ов, фикстура (инстанц тестового класса), не должна разъезжаться по потокам-процессам. (нету thread-safe на уровне фикстуры)
1 лайк

Да лучше бы оформить отдельно.

А на счет юнит фреймворка, интересно ты используешь их :slight_smile:
В общем, на счет распараллеливания, то в моем опыта, как nose так и py.test хорошо справляются с этой задачей. Лично мне больше нравиться работать с py.test так как там через хуки можно запрограммировать практически любую логику, и в том числе для работы с фикстурами.

Вот как есть для py.test https://bitbucket.org/hpk42/pytest-xdist/src/b47ddaa7cc6ceb0345895db32f65861d450982f9/xdist/newhooks.py?at=default

Ну а на счет совместимости 2.7.х и 3.х, какая тут поддержка нужна? чтобы один и тот же написанный код запускался на разных версиях python?

Посмотрю py.test, хочу некоторые тесты запускать под разными питонами, т.к. в той же среде будет жить питон клиент приложения, и подцепить это к тревису.

Ну я могу сказать, что используя xdist в py.test можно запускать тесты в разные потоки под разными версиями интерпретатора, например

py.test -d --tx popen//python=python2.5

В том числе можно настроить удаленный запуск с тем же py.test xdist