简体   繁体   English

避免在Python中使用非Python或无法维护的GUI测试结构

[英]Avoiding an unPythonic or unmaintainable GUI test structure in Python

I am starting a new Python project that will wrap generic GUI testing functionality (developed externally, eg Sikuli) into an application specific framework. 我正在启动一个新的Python项目,该项目会将通用的GUI测试功能(在外部开发,例如Sikuli)包装到特定于应用程序的框架中。 The aim is to make writing test scripts for the application as simple as possible, including reporting test results and handling errors. 目的是使编写用于应用程序的测试脚本尽可能简单,包括报告测试结果和处理错误。

There are many approaches possible, and none seem ideal, however I am very new to Python so there could be something simple yet effective that I am missing. 可能有很多方法,但似乎都不是理想的方法,但是我对Python还是很陌生,因此可能缺少一些简单而有效的方法。 Essentially I am trying to balance clean __init__.py files, ease of use and maintainable structure. 本质上,我试图平衡__init__.py干净文件,易于使用和可维护的结构。

As an example, I would like the script writer to be able to write something like this: 例如,我希望脚本编写者能够编写如下内容:

import framework
import framework.programs.program_f as curr_program
import framework.pages.page_b.area_a as curr_area

if __name__ == "__main__":
    framework.log.start_section("Section 1")

    curr_area.click_button(curr_area.buttons.BUTTON_D)
    curr_program.wait_for_launch()
    curr_program.test_is_running()

    framework.log.end_section()

So, no need for them to create instances of objects (even though I can use objects in the background). 因此,无需它们创建对象实例(即使我可以在后台使用对象)。 However, this layout requires object instances to be created in the package __init__.py files, eg: 但是,这种布局要求在包__init__.py文件中创建对象实例,例如:

|- framework
|   |- log.py
|
|- pages
|   |- page_a
|   |   |- _areas.py (contains class AreaA(AreaBase): ...)
|   |   |- dialogs
|   |   |   |- __init__.py
|   |   |- __init__.py (contains area_a = _areas.AreaA())
|   |
|   |- page_b
|   |- __init__.py
|
|- __init__.py

The alternative is to provide the test writer with classes and rely on the tester to use them sensibly (eg only creating one instance). 替代方法是为测试编写者提供类,并依靠测试者合理地使用它们(例如,仅创建一个实例)。 However, with a package for each page (to keep page-specific files well organised) and a desire to keep __init__.py files mostly empty it could easily result in the need for code like this: 但是,如果每个页面都有一个包(以使组织特定页面的文件井井有条),并且希望使__init__.py文件大部分保持空白,则很容易导致需要以下代码:

curr_page = framework.pages.page_a_pkg.page_a_mod.PageA()
intro_page = framework.pages.intro.intro.Intro()

rather than my original: 而不是我原来的:

curr_page = framework.pages.page_a
intro_page = framework.pages.intro

The first feels unPythonic because of the deep nesting, and repetition. 由于深度的嵌套和重复,第一种感觉不像Python。 The second feels unPythonic because I am masking the use of objects. 第二种感觉与Python无关,因为我掩盖了对象的使用。 I cannot see a third way, and think this may be due to my inexperience with Python. 我看不到第三种方法,并且认为这可能是由于我对Python的经验不足。

Are there any adjustments or alternatives that suit this problem? 是否有任何适合此问题的调整或替代方案? Or even, am I approaching this problem in the wrong way? 甚至,我是否以错误的方式解决了这个问题?

Edited to add: 编辑添加:

A third option would be to use a structure like: 第三种选择是使用如下结构:

framework
|   |- pages
|   |   |- page_a_mod.py
|   |   |- _page_a_pkg
|   |   |   |- page_a-specific stuff
|   |   |   |- __init__.py

But that just turns page_a_mod.py into an extra __init__.py file for _page_a_pkg , but under a different name. 但这只是将page_a_mod.py转换为_page_a_pkg的额外__init__.py文件,但使用了不同的名称。 Same result, just moving the deck chairs around a bit. 同样的结果,只是稍微移动躺椅即可。

While personally, I think there's value in having people achieve at least a baseline level of familiarity with the language and your framework's API so they can be truly effective, you could use one or more context managers to act as a sort of setup state-machine that then drops them in to a context with some already created objects ready for them to use. 就个人而言,我认为让人们至少达到对语言和框架API的基本熟悉水平是有价值的,这样他们才能真正有效,您可以使用一个或多个上下文管理器来充当一种设置状态机然后将它们放到具有一些已创建对象的上下文中,以供它们使用。 Then they could do something like: 然后他们可以做类似的事情:

with test_context('new_user', 'logged_in') as context:

    context.current_area.click_button(....

Though I'd suggest you also look at using a proper unit testing framework, like pyunit or nose , to drive your test scenarios. 尽管我建议您也考虑使用适当的单元测试框架(例如pyunitnose )来驱动测试方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM