问题
I've built a module to hold all of the common selenium expected_conditions which are then referenced throughout various tests. (The selenium portion of this example is not important, just the fact that I have a 'catalog' of a few thousand items.)
# ec module
class EcHR(object):
class sidemenu(object):
hrfile: Clickable = Clickable((By.ID, "sidemenu_HRFile"), f"HR File")
hrvistainfo: Clickable = Clickable((By.ID, "sidemenu_HRVistA Info"), f"HR VistA Info")
class hrfile(__hr_search__):
class actionmenu(__hr_search__.actionmenu):
add: Clickable = Clickable((By.ID, "NewHireLink"), f"Add {BUTTON}")
personnel: Clickable = Clickable((By.ID, 'setEmpType'), f"Personnel Filter {DROPDOWN}")
status: Clickable = Clickable((By.ID, 'setStatus'), f"Status {DROPDOWN}")
configure: Clickable = Clickable((By.ID, "configureLinkGen"), f"Configure {BUTTON}")
reports: Clickable = Clickable((By.ID, 'Reports'), f"Reports {BUTTON}")
class addmenu(object):
employee: Clickable = Clickable((By.ID, f'Employee'), f"Add->Employee {BUTTON}")
Sample reference to a given item in the ec module.
import ec
# navigation helper method for a given page
def do_hrfile_nav(self):
self.clickbutton(ec.EcHR.sidemenu.hrfile)
This works great; I can trace the usage of each object while still providing readability context for what the object is.
self.clickbutton(ec.EcHR.sidemenu.hrfile)
tells the reader we are clicking on the sidemenu item hrfile
on the HR
page. This is important to distinguish from the ec.EcHR.hrfile
which is a different set of objects.
My question: Is there a better/cleaner way to organize these objects? I'm using classes that never get instantiated. (which somehow feels awkward for reasons I can't articulate) These classes act solely as a means to reference them in an organized way. Perhaps some sort of lightweight data object that has class-like structure? (am I over thinking things?)
回答1:
I've got some ideas. It may be useful.
How about using functions as namespaces?
@namespace
def EcHR():
@namespace
def sidemenu():
hrfile: Clickable = Clickable((By.ID, "sidemenu_HRFile"), f"HR File")
return locals()
@namespace
def hrfile():
@namespace
def actionmenu():
add: Clickable = Clickable((By.ID, "NewHireLink"), "Add {BUTTON}")
@namespace
def addmenu():
employee: Clickable = Clickable(
(By.ID, f"Employee"), "Add->Employee {BUTTON}"
)
return locals()
return locals()
return locals()
return locals()
I've changed every class
to a function. And every function must be decorated with namespace
decorator and must return locals()
or any dict
with custom key, val mapping.
Here's NameSpace
class and namespace
decorator.
from functools import reduce
class NameSpace:
def __init__(self, name):
self.__name__ = name
def __str__(self):
return "{}".format(self.__name__)
def __repr__(self):
return "NameSpace({})".format(self.__name__)
def __call__(self):
pass
def namespace(func):
return reduce(
lambda ns, kv: setattr(ns, kv[0], kv[1]) or ns,
func().items(),
NameSpace(func.__name__),
)
The namespace
decorator runs the decorated function and transforms the returned dict
into a NameSpace
instance.
How to access objects?
print(EcHR.sidemenu.hrfile)
print(EcHR.hrfile.actionmenu.addmenu.employee)
来源:https://stackoverflow.com/questions/56674068/organize-objects-using-un-instantiated-classes-as-namespaces