Решил пересмотреть подход к тестам и сейчас тесты (которых пока не очень много), выглядят так:
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?
Код интересен, покажи, если не секрет. Всегда интересно подсмотреть как у кого реализовано
Сам я проектировал не один фреймворк тестирования и последовательно их улучшая, пришёл к простым на первый взгляд, но к сожалению не очевидным изначально вещам. Как то:
Код теста должен быть простым, читаемым и кратким
Тест и фреймворк - раздельные иерархии классов (нельзя тест наследовать от фреймворка. Экземпляр фреймворка должен создаваться в (базовом) классе теста)
Нужно предусмотреть возможность работы из теста с различными интерфейсами AUT (application under test): UI, CLI, DB, API, etc.
Нужно предусмотреть возможность работы из теста с несколькими экземплярами AUT (например, для автоматического тестирования миграции данных или апгрейда)
Нужно предусмотреть возможность работы из теста с несколькими различными AUT: для тестирования интеграции
Это фичи, в соответствии с которыми строится базовая архитектура фреймворка. Ну а работа с различными интерфейсами имеет свою детализацию архитектуры и т.д.
Важно понимать так же, что далеко не всем фреймворкам нужны все эти фичи. Нужно строить архитектуру, исходя из потребностей тестирования конкретного набора AUT
Конечно надо зашарить код.Я думаю, будет полезно посмотреть для других, как можно из разных кусок разных фреймворков реализовать задачу под себя. Это тоже ценный опыт. Потому что кода в наше время на GitHub хватает, надо просто научиться его использовать в своих целях.
Я, например, тоже сейчас делаю проект в котором, много переиспользую код из уже существующих python библиотек для Robot Framework, чтобы ускорить написание автоматизации.
Да и другим также я думаю, будет интересно посмотреть на такую штуку как декоратор и его реализацию.
Ну это зависит от того, что ты хочешь далеко в будущем сделать. По одному тесту тяжело сказать, но перечень python фреймворков для автоматизации я указывал здесь, посмотри может что-то и уже и придумано
Кстати, ты unittest используешь или nose или py.test?
Это пока для меня сложный вопрос. В основе везде лежит unittest.
Привязка под nose только в attr, именно nose запускает под регрессией, имено он отвечает за распараллеливание.
Локально из под ide, я ранаю используя py.test, в первую очередь из-за удобства assert hook
Если, посоветуете что по поводу распараллеливания, то буду благодарен. Тесты сейчас придерживаемся принципа (по некоторым причинам хотелось бы совместимости с Python 2.7.x и 3.x):
порядок независим
из-за “тяжелости” прогрева и возможных side-effecot-ов, фикстура (инстанц тестового класса), не должна разъезжаться по потокам-процессам. (нету thread-safe на уровне фикстуры)
А на счет юнит фреймворка, интересно ты используешь их
В общем, на счет распараллеливания, то в моем опыта, как nose так и py.test хорошо справляются с этой задачей. Лично мне больше нравиться работать с py.test так как там через хуки можно запрограммировать практически любую логику, и в том числе для работы с фикстурами.
Посмотрю py.test, хочу некоторые тесты запускать под разными питонами, т.к. в той же среде будет жить питон клиент приложения, и подцепить это к тревису.