pypom_form
项目描述
pypom_form
pypom_form 是一个基于 PyPOM 的包,它提供了一个基于声明式模式的表单交互页面对象。
pypom_form 旨在通过声明式模式模型,提高在需要与包含表单的页面对象交互时的 UI 和端到端测试自动化的开发者体验。
如果您来自像 SQLAlchemy、Dexterity (Plone) 或旧的 Archetypes (Plone) 这样的框架的使用经验,您应该已经熟悉这种模式:您只需定义一个带有模式的模型,您就可以通过保存或检索数据与您的模型交互。与 pypom_form 类似,模型是页面。
pypom_form 内部基于以下内容
它是如何工作的?
使用 pypom_form,您只需要
实例化一个继承自 pypom_form 提供的 BaseFormPage 类的页面对象实例
声明模式模型
然后您就可以通过仅使用表单与您的页面交互,驱动浏览器,只需输入
page.title = 'the title' page.title
假设您的表单中有一个 标题 字段。
主要概念
您可以将 模式 概念视为一组命名属性(字段),它们将作为常规属性在 模型 上可用。
模式中的每个字段都定义了类型(例如:字符串、整数、浮点数、日期时间、日期、布尔值等),这定义了应用域级别给定字段的数据库类型。
字段有一个引用,可以强制定义或根据字段类型默认分配的小部件。pypom_form提供的小部件内部实现基于PyPOM的区域,因此小部件区域包装和管理包含小部件的DOM。
基本上,小部件通过序列化和反序列化将数据从应用域转换为浏览器域,反之亦然。
你可能认为小部件就像你在设置布尔属性为True或获取表单上的实际值时如何驱动浏览器:基本上这取决于小部件的实现。例如,你可能有一个复选框、是/否单选按钮或组合选择等,如果你想设置True,你驱动浏览器的方式会改变。对日期小部件也是如此。
你还需要处理复杂的小部件,例如
引用小部件(例如:带有搜索、筛选等分层内容导航)
高级多选小部件
字典小部件(键值映射)
等等
例如,假设你正在处理一个假设的高级单选选择字段,你可以访问由小部件区域提供的先进逻辑
page.getWidgetRegion('state').filter('virg').select('Virginia')
或访问验证错误消息、标签文本等。
为什么选择pypom_form
显然,你可以在自动化测试中使用纯selenium/splinter或使用传统的纯页面对象模型模式来驱动浏览器,但与pypom_form相比,你有以下优点
一次编写、可重用方法,如果测试CMS框架非常实用
页面和小部件逻辑的关注点分离
声明性模式方法
可重用模式和Widgets,无需代码重复
Widgets可以通过pypom_form与其他项目共享
简单的基于自动生成的getter和setter的API
通过基于PyPOM的区域小部件与高级小部件逻辑交互
小部件隔离。所有元素查询都针对根区域运行,而不是页面根
更简单的输入元素选择器,它们相对于区域小部件根是相对的
模式表单改进了如何记录包含表单的页面(属性名称、类型、小部件、允许的词汇表等)。你需要知道的所有内容都在模式级别定义,整个图景一目了然
如果你要测试基于colander/deform的应用程序(可能你正在测试基于Pylons Pyramid 的Python基于Web的应用程序),则支持重用现有的模式
支持页面和模式继承
易于测试具有相同数据模型、相同或不同选择器或小部件类型的单皮肤或多皮肤Web应用程序。因此,你可以重用所有页面对象类,它们被定义的方式,只有模式小部件选择器和类型发生改变
小部件区域是PyPOM区域,因此如果你想访问小部件容器内的内部元素,生成的选择器将更简单,因为它们相对于小部件区域根。此外,也支持子/嵌套区域或动态区域
使用应用域数据而不是浏览器域数据与你的模型交互。这更简单、更容易管理Python数据(例如,你设置12.9而不是‘12.9’,对于日期时间值也是如此,如datetime.now())
支持链式调用,如page.set('title', 'the title')
支持通过page.update(**values)通过在模式级别定义的顺序进行批量字段更新
不要重新发明轮子。它基于现有的和广泛使用的组件,如plain PyPOM或Colander库
如果你已经熟悉schema声明性模型,如SQLAlchemy、Archetypes(Plone)、Dexterity(Plone)或表单库如deform,将提供相同的用户体验
由于小部件实现基于区域,你可以在页面加载时简单地执行page.name = "the name",而不是在设置值之前必须调用等待方法:小部件能够在获取或设置数据之前等待小部件加载
页面对象类更简单,代码更少,即使不同的测试工程师实现页面表单逻辑,也更具标准性:存在一种结构模式
此外
100%测试覆盖率
支持Python 2和3
支持Splinter驱动程序(Selenium支持尚未可用)
由于pytest-splinter,pytest设置就绪
代码示例
以下代码示例假设存在一个提供使用Splinter驱动程序构建的页面实例的导航固定装置,但你也可以根据PyPOM文档自己构建页面实例
Schema定义
import colander from pypom_form.form import BaseFormPage class BaseEditSchema(colander.MappingSchema): """ This is the base edit mapping common for all pages """ name = colander.SchemaNode( colander.String(), selector=('id', 'name-widget'), ) class BaseEditPage(BaseFormPage): """ This is the base edit class """ schema_factory = BaseEditSchema
假设你有一个可以与之交互的页面实例,你可以通过设置一个属性来操作上述页面
@pytest_bdd.when(pytest_bdd.parsers.parse( 'I set {name} as name field')) def fill_name(navigation, name): page = navigation.page page.name = name
你也可以定义具有扩展schema的其他页面,例如整数类型
class AnotherPageEditSchema(BaseEditSchema): duration = colander.SchemaNode( colander.Int(), missing=0, selector=('id', 'duration-widget'), validator=colander.Range(0, 9999))
但你也可以创建类似于colander.Bool或任何其他colander支持的类型。
并且测试
@pytest_bdd.when(pytest_bdd.parsers.cfparse( 'I set {duration:Number} as Alarm duration', extra_types=dict(Number=int))) def fill_alarm_duration(navigation, duration): page = navigation.page page.duration = duration
你可能会注意到在上面的例子中,你设置了一个整数持续时间而不是字符串。例如,你可以执行page.duration += 10。
如果默认实现不符合你的应用程序上的实现(例如,非标准的复选框用于布尔小部件),你还可以在字段上定义自定义小部件,例如一个pretend MyBooleanWidget
mybool = colander.SchemaNode( colander.Bool(), missing=False, selector=( 'id', 'mybool-widget' ), pypom_widget=MyBoolWidget() )
也支持链式调用(例如:设置标题,执行pretend提交方法,然后设置布尔值)
page.set('title', 'the title'). \ .submit(). \ .set('mybool', False)
或批量更新。所有更改都遵循schema级别的字段顺序
page.update(**{'title': 'the title', 'mybool': True})
可以使用update或raw_update在测试预条件创建中使用。假设你有一个具有复杂配置的通用给定步骤,你可以传递原始json数据,raw_update将负责将数据从浏览器模型(例如:字符串)转换为页面模型(字符串、整数、日期时间等)
@pytest_bdd.given(pytest_bdd.parsers.cfparse( 'I have a CAN bus protocol configured with:\n{raw_conf:json}', extra_types=dict(json=json.loads))) def create_can_protocol(navigation, base_url, raw_conf): """ create a can protocol """ navigation. \ visit_page('CANBusProtocolsPage'). \ wait_for_full_spinner(). \ click_add(). \ raw_update(**raw_conf). \ save(). \ wait_for_success_pop_up_appears(). \ click_on_ok_pop_up()
假设在.feature文件中指定了raw_conf的json格式,例如
@UI @edit @CANBusParameter Scenario: Add a CAN bus parameter Given I am logged in as Administrator And I have a CAN bus protocol configured with: {"name": "The name", "baudrate": "250", ... } And ...
如上述代码示例所示,在页面加载时与表单交互之前不需要执行等待调用,因为每个小部件都能够等待其控制的输入元素就绪。等待逻辑已经在小部件级别上定义,并且你可以覆盖它们。
变更日志
0.3.1 (2017-10-24)
添加了raw_dump方法来获取所有字段的序列化。
0.3.0 (2017-10-10)
添加了dump方法来获取所有字段的大批量。
0.2.3 (2017-09-14)
现在你可以覆盖自动生成的方法,并在其中调用super
0.2.2 (2017-07-03)
将test_fields.py移动到正确的位置。
如果已经存在,不要覆盖页面和区域上的update和raw_update方法。
0.2.1 (2017-06-01)
更新电子邮件项目
0.2.0 (2017-01-24)
功能
在组件基类实现中添加了 序列化 和 反序列化 方法,以便进行高级使用。这样,您只需覆盖上述方法即可轻松实现复杂/组合组件(例如:从页面模型数据到浏览器或组件内部表示数据的中间转换)。
为在需要实现复杂或组合组件时添加了 ObjectType 字段。
添加了对 readonly 字段的支持。如果字段被标记为只读,则不会执行浏览器交互。
0.1.0 (2017-01-03)
功能
将组件引用添加到组件区域,以便您可以从组件区域导航到组件并访问在模式中指定的组件选项。
添加了 TextAreaWidget。
文档
改进了文档
0.0.1 (2016-12-22)
初始版本
pypom_form-0.3.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0b65ab4c5250c79be237600d4ed5b9ca5ea025619bc0320eed9602c4f17f81d2 |
|
MD5 | 2dc60699d52964668f8e732596f6f13e |
|
BLAKE2b-256 | a3ab10ef782713f272d9d4da6fe79cebb123e54d27f0062c2d7d645b8cb539a1 |