У меня есть класс «Wrapper». Wrapper наследуется от объекта, и основная ответственность заключается в том, чтобы перехватывать вызовы метода селену во время теста. Это __init__
метод подписиПредоставить доступ к области возможностей для себя, где он называется?
__init__(self, object_to_wrap, actions={}, **kwargs)
Часть его функциональности взять словарь в качестве аргумента в методе инициализации, и разоблачить ключи в качестве атрибутов на object_to_wrap
объекта, определяя __getattr__
магический метод (подпись: __getattr__(self, item):
) и проверка ключей self.actions
на item
. Если он найден, метод вызывается.
В тестовом коде инициализации будет выглядеть так:
def navigate(scoped_self, to=''):
self.driver.switch_to_default_content()
self.driver.switch_to.frame(to)
scoped_self.navigations.append(to)
# the navigate method is scoped in an
# instance method of the test class, so it has access to self
Итак, мой вопрос, как я могу сделать сферу, или self
в описанном выше способе, быть сфера моего Wrapper
класса , а не тест-класс?
Для ясности, если решение, которое я ищу в этом вопросе было найдено, реализация навигации изменится быть:
def navigate(scoped_self, to=''):
self.object_to_wrap.switch_to_default_content()
self.object_to_wrap.switch_to.frame(to)
Кроме того, для ясности, я уверен, что я ищу это именно то, что выполняет Javascripts Function.prototype.bind
.
UPDATE: Определение методов, такие как плавание, внутри класса Wrapper это не вариант, как класс Упаковочного не есть может тест реализующей логики. Набор тестов выполнен на n> 1 DOM, которые полностью не связаны. Например, один из тестов требует метода «alert_handlers» (для перезаписывания функции window.alert и возврата предупреждений, представленных в виде строки), другой может потребовать метод навигации, а третий может потребовать и то, и другое.
UPDATE # 2: Благодаря ниже ответ от c17r, я понял, что без GetAttribute код, включенный в моем примере, что, казалось бы, как если бы я просил что-то мы уже выполнена. То, что я ищу, - это способность, в приведенном выше методе навигации, для scoped_self
быть экземпляром Wrapper.
Кроме того, я специально искал способ «динамически» передать scoped_self к функциям (таким образом, что Function.prototype.bind
«динамически» устанавливает this
где this
является myEventListener.bind (окно), если вы не знакомы с JavaScript, сделать слушатель событий на теле и console.log this
без связывания, а затем с креплениями, чтобы увидеть разницу)
Кроме того, я полагал, что это может помочь привести пример реализации без решения Я ищу для. Это в настоящее время работает, как ожидалось:
class Wrapper(object):
def __init__(self, wrapped, actions={}):
self.wrapped = wrapped
self.actions = actions
self.navigations = [] # EXAMPLE, SEE THE TEST CLASS CODE
def __getattr__(self, item):
if item in self.actions:
return self.actions[item]
# do other fancy stuff here
# UPDATE #2: added for clarity. this is the current implementation
orig_attr = self.wrapped.__getattribute__(item)
if callable(orig_attr):
def hooked(*args, **kwargs):
self.pre(item, *args, **kwargs)
self.err = False
try:
result = orig_attr(*args, **kwargs)
except Exception as e:
#logs
self.post(*args, **kwargs)
raise
if type(self.wrapped) == type(result):
return self
return result
return hooked
else:
return orig_attr
class SomeTest():
#blah blah init stuff, set self.driver = selenium.webdriver.Phantomjs
def spawn_actions(self):
def navigate(scoped_self, to=''):
self.driver.switch_to_default_content()
self.driver.switch_to.frame(to)
scoped_self.navigations.append(to) # <--- appended to wrapper.navigations
return {'navigate': navigate}
def run(self):
driver = Wrapper(self.driver, self.spawn_actions())
driver.get(url)
driver.navigate('New Request')
# fun tests!
Ты правильно меня поняли, и я извиняюсь за оставляя все __getattr__ (для краткости). см. мое обновление о том, как выглядит фактическая реализация. Обратите внимание, что будет вызвано более одного метода экземпляра, который я не буду включать в код снова для краткости (и потому, что он слишком близок к производственному коду для нашего продукта) – h3xc0ntr0l
Однако, тщательно перечитав свой код, я считаю, я ответил на мой вопрос :) Я проверю, как только я доберусь до машины, где у меня есть реализация. – h3xc0ntr0l