如何在Python中正确处理大量(格式)常量?
我正在 Python 中使用 Selenium 建立一个端到端测试框架。为了单击 DOM 元素,我必须定义许多定位器(如 XPath、CSS 选择器等),这些定位器大多是不变的。
但是,有一些常量在每次运行中都会有所不同,因此需要在运行时格式化某些内容。
目前我有一个基本的 locators.py 文件,它以视图对应的方式组织所有常量,如下所示:
class Locators:
class LoginPage:
USERNAME_INPUT = "//input[@id='username']"
PASSWORD_INPUT = "//input[@id='password']"
LOGIN_BUTTON = "//button[text()='Login']"
# ...
class Homepage:
ACTION_BUTTON = lambda t: f"//buton[text()='{t}']"
# ...
# ...
然后可以像这样使用:
from locators import Locators
browser.click(Locators.LoginPage.USERNAME_INPUT)
browser.click(Locators.Homepage.ACTION_BUTTON(var))
这里的最后一个示例(ACTION_BUTTON
)是我最感兴趣的。由于例如 PyCharm 显示 PEP 8 警告,不鼓励使用 lambda,我想知道是否有更优雅的方法来处理此类“可格式化”常量?
此外,我希望能够将所有按钮概括为外部类,如下所示:
class Locators:
_BUTTON = lambda s: f"//button[text()='{s}']"
class LoginPage:
USERNAME_INPUT = "//input[@id='username']"
PASSWORD_INPUT = "//input[@id='password']"
LOGIN_BUTTON = _BUTTON("Login")
class Homepage:
ACTION_BUTTON = _BUTTON
但这会产生语法错误。
I am setting up an end-to-end testing framework with Selenium in Python. In order to click on DOM elements I have to define a lot of locators (like XPaths, CSS-selectors etc.) which are mostly constant.
However, there are some constants that vary in each run, so some content needs to be formatted in at runtime.
At the moment I have a basic locators.py
file which organizes all of the constants in a view-corresponding way like this:
class Locators:
class LoginPage:
USERNAME_INPUT = "//input[@id='username']"
PASSWORD_INPUT = "//input[@id='password']"
LOGIN_BUTTON = "//button[text()='Login']"
# ...
class Homepage:
ACTION_BUTTON = lambda t: f"//buton[text()='{t}']"
# ...
# ...
This can then be used like this:
from locators import Locators
browser.click(Locators.LoginPage.USERNAME_INPUT)
browser.click(Locators.Homepage.ACTION_BUTTON(var))
The last example here (ACTION_BUTTON
) is of most interest to me. Since e.g. PyCharm displays a PEP 8 warning that using lambdas is discouraged I wonder whether there is a more elegant way of handling such "formattable" constants?
Furthermore, I would like to be able to generalize e.g. all buttons to the outer class like this:
class Locators:
_BUTTON = lambda s: f"//button[text()='{s}']"
class LoginPage:
USERNAME_INPUT = "//input[@id='username']"
PASSWORD_INPUT = "//input[@id='password']"
LOGIN_BUTTON = _BUTTON("Login")
class Homepage:
ACTION_BUTTON = _BUTTON
But this gives a syntax error.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想这取决于个人风格。
就我个人而言,我会在此用例中使用常规格式字符串。
I guess this is up to personal style.
Personally I would use regular format strings for this use case.
我没有发现将辅助函数放在 Locators 命名空间之外有任何问题。毕竟,在执行之前它们不是定位器。
话虽这么说,我遇到了一个非常相似的问题。我通过为需要在定位器字符串中引用的变量创建一个单独的命名空间来解决这个问题。这允许我运行一些设置逻辑来确定在加载模块之前变量应该是什么。
如果您需要模块更动态地加载(就像我所做的那样),那么您将面临必须在函数内部限定字符串范围的问题。
I don't see any issues with putting your helper functions outside the Locators namespace. Afterall, they are NOT locators until they are executed.
That being said I ran into a very similar problem. I solved this by creating a separate namespace for the variables that would need to be referenced in the locator strings. This allowed me to run a some setup logic to determine what the variables should be prior to loading the module.
If you need the module to load a little more dynamically (like I did), then you're faced with having to scope strings inside of functions.