多用户web/mail/sms应用程序的行为驱动开发测试

behaving的Python项目详细描述


behaving
==br/>

*behaving*是一个用于
行为驱动开发的web应用程序测试框架,基于"behaving"和"splinter"。

*behaving*是用python编写的,类似于"cucumber"或"莴苣"。
*behaving*添加了多用户web/ema的步骤库il/sms/gcm
交互,并提供python*behaving*名称空间,以便独立的步骤库可以一起工作。

请参阅*behaving*的优秀文档<;http://pythonhosted.org/behaving/>;``有关如何使用、如何编写自定义步骤和使扩展*behaving*


hello world
----


开始使用*behaving*非常简单。在一些python模块中,添加由一个或多个场景组成的*特性*。这些特性是扩展名为`.feature``的小黄瓜语言文件。在同一个目录中,您应该有一个步骤模块,它可以导入*behaving*步骤以及您自己的自定义步骤(稍后在setup节中详细介绍)。下面是一个基本示例:




功能:文本显示


背景:
给定浏览器

场景:当我访问"http://www.wikipedia.org/"时搜索bdd
,然后用"bdd"填写"search"
我按"开始"键,然后我会在5秒内看到"行为驱动的开发"




以及GCM服务器。这些步骤包含一小部分,允许您执行以下操作:




feature:email&sms

scenario:click link in a email
给定浏览器
当我向主题为crypho、正文为try o o的"foo@bar.com"发送电子邮件时但是我们的产品在http://crypho.com"
我点击了我在"foo@bar.com"收到的电子邮件中的链接
然后浏览器的URL应该是"http://crypho.com/"


场景:当我用body向"+474569001"发送短信时,接收body
llo world"
然后我应该在"+474569001"收到一条包含"world"


场景:接收gcm通知
当我发送gcm消息"{"到":"deviceid","data":{"消息":"foo bar","badge":6}"
然后我应该接收gcm notif"设备ID"中包含"{'data':{'message':'foo bar'}"


----


现在很多web应用都依赖于多用户交互。为了帮助您进行这些交互,*behaving*使用了*personas*的概念。测试中的角色在其自己的浏览器实例中运行,您可以同时运行多个角色(及其浏览器实例)。通过调用

::


当第一次调用一个角色时,它被创建为一个空字典。您可以使用设置的值预定义角色。

让我们以熟悉的lotr字符作为测试用户。在设置测试环境时(详见后面的设置部分),我们设置测试中可能需要的字符基本变量:





personas={
'frodo':dict(
fullname=u'frodo baggins',
email=u'frodo@shire.com',
密码=u'frodopass',
移动电话='+474569001',
地址:{
街道:"郡",
邮政编码:"4321"
}



'gandalf':dict(
全名=u'gandalf the grey',
电子邮件=u'gandalf@wizardry.com,
密码=u'gandalfass',
手机='+474569004',
地址:{
街道:"Rivendell Street 1",
邮编:"1234"
}


}

/>def before_scenario(context,scenario):

context.personas=personas



在测试和给定的persona中,现在可以使用`$var_name``来访问persona的变量。也可以在角色上设置新变量。所以下面,




将"dress.country"设置为"country"
,并将"postaddress"设置为:
"
$fullname
$address.street,$address.zip,$address.country
""


变量"title"到id为"document title"的元素的文本,并重用变量"title"来填充id为"delete"的字段。它还将id为"country"的字段的值存储在addre s s[``country`]中。
`$var_name``模式也可用于通过预期文本正文的步骤接收的文本中,这意味着``postaddress`` persona变量将包含gandalf的完整snail mail postage address在多行上有很好的格式。

----


让我们假设下面的场景(来自一个真实的例子)。` crypho``是一个在线消息/共享网站,为用户提供端到端加密实时通信。*behaving*是为了帮助测试crypho而编写的。

在crypho中,团队在*空间*中协作。要在某个空间邀请某人,被邀请者必须与邀请者共享一个令牌,以便双方都可以验证对方的身份。

::


功能:frodo邀请甘道夫到shire空间


给定状态"shire"

场景:frodo邀请甘道夫到shire空间re

这将向数据库预加载数据、设置服务器等,然后执行场景:

首先gandalf登录。"给定"甘道夫"作为角色"的步骤,会启动属于甘道夫角色的浏览器。下一步,``当我登录``是一个自定义步骤,定义如下:

::


@when('i log in')
def log-in(context):


assert context.persona
context.execute_steps(u""
当我回到家中
n element with id"email"在2秒内
当我在"email"中填写"$email"
并按"send sms"
时,我将在2秒内看到"我们已向您发送了带有安全代码的短信"
,我将在"$mobile",我用"$token"填写"token"
,用"$password"填写"password"
,然后按"login"
时,应该启用"token"。然后我应该在5秒内看到"crypho"
")

t persona(甘道夫)解析它收到的短信,并将其保存为"令牌"。稍后,gandalf会重新使用它来填充双因素身份验证字段。

现在gandalf已经登录,测试将使用frodo进行。弗罗多将登录,并邀请甘道夫进入私人空间。

::


/>我按"邀请成员"
然后我会在1秒内看到"邀请成员"
当我用"gandalf@wizardry.com"填写"被邀请者"时,我会在"邀请消息"中填写"来加入我们!"
然后我按"发送邀请"
然后我将在2秒内看到"您的邀请已发送"



一旦发送邀请,我们将切换回Gandalf的浏览器,Gandalf应该已经在其浏览器中收到通知以及电子邮件。然后他用完成邀请的代币给佛罗多发了一条短信。

::


包含"frodo baggins"的ardry.com邀请您加入crypho的私人工作区
当我单击包含"邀请"文本的链接
并单击包含"待定邀请"文本的链接
时,我将看到"来吧加入我们!"
当我将"token"设置为"invitation token"文本时
我将短信发送到"4569900",并将正文"$token"

我在"4569900"
收到的短信的日期,我用包含"邀请"的文本单击链接,用包含"输入授权令牌"的文本单击链接,然后用"$frodokoken"
填写"身份验证令牌",然后按"提交"t"
然后我会看到"邀请已被接受"。在5秒内
我会看到"灰色甘道夫加入了空间,由弗罗多·巴金斯邀请"在10秒内

您可以在视频上看到正在进行的测试'here<;http://vimeo.com/63672466/>;`.

/>
def before_scenario(context):
context.single_browser=true

。_设置:

设置测试环境
--------


从使用"pip"或"easy_install"安装"behaving"开始。这还将安装依赖项并创建用于调用测试的"behave"脚本。如果您喜欢使用BuildOut,请从其存储库克隆包本身,它已包含BuildOut配置。

通常您将拥有一个包含所有功能和步骤的文件夹。例如,目录结构如下:

::


features/
features/mytest.feature
features/myothertest.feature
features/environment.py
features/steps/
features/steps/steps.py

改变你需要的行为步骤。您还可以定义自己的步骤。因此,"steps.py"可能看起来像:





from behaving import when
from behaving.web.steps import*
from behaving.sms.steps import*
from behaving.mail。步骤导入*
从behaving.notifications.gcm.steps导入*
从behaving.personas.steps导入*

@when('i go to home')
def go_to_home(context):
context.browser.visit('https://localhost:8080/')

好吧,在测试的不同阶段需要发生的事情,比如在所有事情之前和之后,一个特性运行,或者一个场景运行。为了方便起见,您可以导入并重用"behaving.environment",它将执行默认操作,如在场景结束后关闭所有浏览器、清理电子邮件文件夹等。

还可以使用"behaving.web.environment"、"behaving.mail.environment"、"behaving.sms.environment"``以及"behaving.personas.environment",如果你不需要短信的话。

从将导入环境行为为benv



def before_all(context):
import mypackage
context.attachment_dir=os.path.join(os.path.dirname(mypackage.u file)、"tests/data")
context.sms_path=os.path.join(os.path.dirname(mypackage.\u file\uu)、'../../var/sms/')
context.gcm\u path=os.path.join(os.path.dirname(mypackage.\u file\uu)、'../../var/gcm/')
context.mail\u path=os.path.join(os.path.dirname(mypackage.\u file\uu)、'../../var/mail/')
benv.before\u all(context)




def af全部(上下文):
benv.after-all(上下文)



def before-u-feature(上下文,特征):
benv.before-u-feature(上下文,特征)



def after-u-feature(上下文,特征):
benv.after-u-feature(上下文,特征)


def before-u-scenario(context,scenario):
benv.before_scenario(context,scenario)
context.personas=personas

def after_scenario(context,scenario):
benv.after_scenario(context,scenario)

s:

*``屏幕截图目录``(保存屏幕截图的路径。如果设置了此选项,则场景中的任何故障都将导致出现故障时浏览器的屏幕截图。)
*``attachment_dir``(可以找到文件附件的路径)
*``sms_path``(smsmock``用来保存短信的路径)。默认为``current\u dir/sms`)
*``gcm\u path```(``gcmmock``用来保存gcm通知的路径)。默认为``current_dir/gcm``)
*``mail_path```(由``mailmock``用来保存邮件的路径。默认为``当前目录/邮件``)
*``默认浏览器`
*``默认浏览器大小``(元组(宽度、高度),在创建时应用于每个浏览器)
*``最大浏览器尝试次数``(如果失败则重试创建浏览器的次数)
*``远程Web驱动程序`(是否使用remote网络驱动程序。默认为``false`)
*``browser_args``(创建浏览器时使用的附加关键字参数的dict)
*``base_url``(浏览器的基本URL,允许您使用相对路径)


/>
对于chrome和docker问题,下面的代码很有用:




r/>}


mail、gcm和sms mock server
您可以在运行测试之前直接调用它们,它们都是创建一个端口和一个目录,将数据作为参数输出。例如,



./bin/smsmsmock-p 8081-o./var/sms
./bin/gcmmock-p 8082-o./var/notifications/gcm
./bin/mailmock-p 8083-o./var/mail[--no stdout]

``behaving.web``支持的匹配器/步骤/>*浏览器

*给定浏览器
[打开默认浏览器,即firefox]
*给定"brand"作为默认浏览器
[将默认浏览器设置为"brand",这是使用远程webdriver或firefox、chrome、safari或phantomjs时的浏览器名称]
*给定cordova作为默认浏览器
[用于cordova移动应用程序]
*给定electron应用程序"``app_path`"
[用于基于electron的桌面应用程序]
*给定浏览器"``name``"
[在重新加载时打开名为``name``]
**当我返回
*当我前进
*当我将浏览器大小调整为"width``x``height``
*当我拍摄屏幕快照时,[如果在环境中设置了"screenshots`u dir`",将保存浏览器的屏幕快照NT。此外,如果设置了"screenshots\u dir",则所有失败的测试都将生成一个屏幕截图。]
*当我执行脚本"script`"
*当我将cookie"key`"设置为"value`"
*当我删除cookie"key`"
*当我关闭浏览器"``name``"

*当我切换到带有css"``css`"的框架时

*当我切换回主页时

*window s

*当我在"``url`"打开名为"``name``"的新窗口时
*切换到名为"``name``"

*url

*给定基url"``url`"
[将基url设置为"url``",或者直接在"environment.py``"中设置"context.base```"
*当我访问"``url`"
*时转到"``url`"
*的窗口url路径并设置"`{expression}`"
*然后浏览器的url应该是"``url`"
*然后浏览器的url应该包含"``text`"
*然后当我单击指向"``url`"
*的链接时,浏览器的url不应该包含"``text`"
*当我单击包含文本"``text``"
*的链接时,当我单击包含文本"``text`"
*的链接时,请单击指向包含"``text``"

*文本的链接;当我显示元素w时,请单击指向该元素的链接id为"``id``"
*当我隐藏id为"``id``"

*text

*的元素时,我应该看到"``text``"
*然后我不应该看到"``text`"
*然后我应该看到"``text``"在"`timeout``秒内
*然后我不应该看到"``text`"在'timeout``seconds

*id

*在'timeout``seconds

*css

*existence

*css选择器为'``selector``'
*的元素,则不应看到css选择器为'``selector```'
*的元素。n我应该在"timeout"秒内看到一个css选择器为"selector"的元素
*然后在"timeout"秒内没有看到一个css选择器为"selector"的元素
*然后我应该在"css"选择器为"css"的元素
*那我至少该看看在"timeout"秒内使用css选择器"``css`"的元素

*可见性

*然后使用css选择器"``css`"的元素应可见
*然后在"timeout"秒内使用css选择器"``css`"的元素应可见
*然后带有css选择器"`css`"的元素不应可见
*然后带有css选择器"`css`"的元素应在"超时"秒内可见
*然后带有css选择器"`css`"的{n:d}元素应可见
*那么具有css选择器"`css`"的{n:d}元素应该在"timeout``秒内可见
*那么至少具有css选择器"`css`"的{n:d}元素应该在"timeout``秒内可见
*然后至少具有css选择器"`css`"的{n:d}元素应该在"timeout``秒内可见"thin``timeout``seconds

*元素上存在类

*然后xpath为"xpath"的元素应该有类"`cls`"
*然后xpath为"xpath`"的元素不应该有类"`cls`"
*然后elemxpath为"xpath"的ent应该在"timeout"秒内具有类"`cls`"
*然后xpath为"xpath"的元素不应该在"timeout"秒内具有类"`cls`"
*然后"`name`"应该具有类"`cls`"
*``name```不应该有类'`cls``'
*那么'`name``应该有类'`cls```在'`timeout``seconds
*那么'``name```不应该有类'`cls````在'`timeout:d``seconds

*xpath

*那么我应该看到一个el带有xpath"``xpath`"
*的元素,则不应看到带有xpath"``xpath``"
*的元素,则应看到带有xpath"``xpath``"的元素,在``timeout``seconds
*的元素,在``timeout``seconds


*当我清除字段"``name``"
*当我键入"``value``"到"``name`"
[与fill相同,但会缓慢触发键盘事件]
*当我从"``name``"中选择"``value``"时,
*当我从"名称"中选择"值"时,请勾选"``name``"
*当我从"名称``"
*中选择"文本"时,请勾选"``name```"
*当我在附加时按"``name` id` text` innertext`"
*当我按带有xpath"``xpath`"的元素时当我将id为"id```的元素的内部html设置为"contents``"
[将id为"id``的"contentEditable``元素的内部html设置为"contents`"
*当我将类为"class``的元素的内部html设置为"contents`"时``"
*当我将类为"``class``"的元素的内部html设置为"``contents`"
*当我将"``key`"发送到"``name`"
*当我关注于"``name``"
*时,字段"``name`"应该具有"``value`"
*则应启用"``name`"
*当"``name``"应被禁用时
*则不应启用"``name``"
*然后"``name``"应有效
*然后"``name``"应无效
*然后"``name``"应无效
*然后应要求"``name``"
*然后"``name`"不应有效必需的

*当我在警报中输入"``text``"时,警报和提示
*当我接受警报时,
*当我解除警报时,
*我应该看到警报
*然后我应该在"timeout``秒内看到警报
*然后我应该看到警报继续如果输入"``text`"
*则我会在"超时"秒内看到包含"``text``"的警报

*鼠标

*当我用xpath"``xpath``"
*当我用xpath"``xpath`"

*从元素中鼠标取出

*时,应该在"超时"秒内下载包含"文本``"内容的文件"``filename``"
*n文件"file name`"应该在"timeout``seconds

*persona interaction&;variables

**当我计算脚本"script``"并将结果分配给"key`"



``behaving.mail``支持的匹配器/步骤时
``地址```并设置"``表达式`"
*然后我将在"``地址`"
*收到一封电子邮件,然后我将在"``地址`"收到一封电子邮件,主题为"``主题`"
*然后我将在"``地址`"收到一封电子邮件,其中包含"``文本`"
*然后我将在"``地址"收到一封电子邮件``"带有附件"``filename`"
*则我不应在"``address`"

`` behaving.sms``支持的匹配器/步骤
----------

*当我将"``key``"设置为在"``number`"
*处收到的sms正文时我在"``number``"收到并设置"``expression`"
*然后我在"``number``"
*收到一条短信,然后我在"``number``"收到一条包含"``text`"

`` behaving.notifications.gcm``支持的匹配器/步骤的短信
*当我发送gcm消息"{"到":"deviceid","data":{"message":"foo bar","badge":6}"
*然后我应该在"deviceid"处收到一个gcm通知,其中包含"{data':{message':'foo bar'}"
*然后我应该在"deviceid"处收到任何gcm通知

`` behaving.person作为"受支持的匹配器/步骤"
——人物角色"``source`"设置为"``target`"
*然后"``key``"设置为"``value`"


调试
--


*当我暂停有助于行为的测试时请参阅"贡献准则"


。_`黄瓜:http://cukes.info/
…_`生菜:http://莴苣.it/
…_` behave`:http://pypi.python.org/pypi/behave
。_` splinter`:http://splinter.cobrateam.info/
。_` crypho`:http://crypho.com
_`贡献指南`:https://github.com/ggozad/behaving/blob/master/contribution.rst

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java在Windows 7上配置Apache Ant和Ivy   java使用带有片段的节,NullPointerException   java如何使用Gradle设置环境变量,而不是在Exec范围内?   JavaEclipse(3.5和3.6)在ubuntu中崩溃   java如何通过引导类加载器以编程方式加载另一个类?   java无法使用自定义视图在画布上绘制   java使用Spring引导邮件发送html表   java“\n”在导出到时不工作。jar文件   amazon web services在AWS SDK for Java v2上添加了Gradle依赖项   java在包含ClientBundle的包中有一个成员ClientBundle是一种好的做法吗?   java如何在JDBC中建立连接池?   java线程安全但快速访问“最终最终”变量?   谷歌地图上的MarkerDrag没有更新标记的。getPosition()Android Java   javajavaconfig:javax类型。servlet。ServletContext和javax。servlet。无法解析ServletException   无法使用JAVAXB从Java中的XML文件读取数据   java Change ImageView触控可绘制矢量颜色   java在JUnit5中,如何模拟返回void的静态方法?我们可以使用导入组织吗。莫基托。模仿静态?   继承如何将这个Java接口和继承结构转换为Golang?   多个请求的java httpclient超时   JavaSelenium不能使用Actions类来执行只需几个步骤的操作,有什么问题吗?