行为驱动:自然语言映射到程序代码 应用场景:敏捷场景里用 (注释:行为驱动在敏捷开发里的应用)
注意事项:
1.目前lettuce只支持python2;lettuce 在这个路径 C:\Python27\Scripts
步骤:前置条件 py -2 -m pip install lettuce
2.必须新建features目录,否则执行会失败,目录结构如下:
features
-steps.py(写测试脚本和自然语言的测试步骤进行对应)
-xxxx.feature (写自然语言的测试步骤的)

运行:
法一:在features上级的目录下打开cmd 执行CMD命令,进来后,输入lettuce;features这个目录文件夹 是自己创建的
法二:在cmd中,cd进入features的父目录,执行lettuce

E:\PythonDemo\Glory\20190224\features
steps.py
zero.feature
就这俩文件

steps.py

#encoding=utf-8
from lettuce import *#用于计算整数的阶乘函数
def factorial(number):number = int(number)if (number == 0) or (number == 1):return 1else:return reduce(lambda x, y: x * y, range(1, number + 1))@step('I have the number (\d+)')
def have_the_number(step, number):# 将通过正则表达式匹配的数字存于全局变量world中world.number = int(number)@step('I compute its factorial')
def compute_its_factorial(step):# 从全局变量world中取出匹配的数字,# 计算其阶乘,并将结果再存回world中world.number = factorial(world.number)@step('I see the number (\d+)')
def check_number(step, expected):# 通过正则匹配到预期数字expected = int(expected)# 断言计算阶乘结果是否等于预期assert world.number == expected, "Got %d" %world.number

zero.feature
Feature: Compute factorial
In order to play with Lettuce
As beginners
We’ll implement factorial

Scenario: Factorial of 0
Given I have the number 0
When I compute its factorial
Then I see the number 1

Scenario: Factorial of 1
Given I have the number 1
When I compute its factorial
Then I see the number 1

Scenario: Factorial of 2
Given I have the number 2
When I compute its factorial
Then I see the number 2

Scenario: Factorial of 3
Given I have the number 3
When I compute its factorial
Then I see the number 6

方法二“
私有,排重的方法,都不会跟测试步骤对应

第一个用函数
E:\PythonDemo\Glory\20190224\features
上面那2个文件

第2个用类的方法
E:\PythonDemo\Glory\201902241\features
steps.py zero.feature

steps.py

#encoding=utf-8
from lettuce import world, stepsdef factorial(number):number = int(number)if (number == 0) or (number == 1):return 1else:return reduce(lambda x, y: x * y, range(1, number + 1))@steps
class FactorialSteps(object):"""Methods in exclude or starting with _ will not be considered as step"""exclude = ['set_number', 'get_number']def __init__(self, environs):# 初始全局变量self.environs = environsdef set_number(self, value):# 设置全局变量中的number变量的值self.environs.number = int(value)def get_number(self):# 从全局变量中取出number的值return self.environs.numberdef _assert_number_is(self, expected, msg="Got %d"):number = self.get_number()# 断言assert number == expected, msg % numberdef have_the_number(self, step, number):'''I have the number (\d+)'''# 上面的三引号引起的代码必须写,并且必须是三引号引起# 表示从场景步骤中获取需要的数据# 并将获得数据存到环境变量number中self.set_number(number)def i_compute_its_factorial(self, step):"""When I compute its factorial"""number = self.get_number()# 调用factorial方法进行阶乘结算,# 并将结算结果存于全局变量中的number中self.set_number(factorial(number))def check_number(self, step, expected):'''I see the number (\d+)'''# 上面的三引号引起的代码必须写,并且必须是三引号引起# 表示从场景步骤中获取需要的数据以便断言测试结果self._assert_number_is(int(expected))FactorialSteps(world)

zero.feature
Feature: Compute factorial
In order to play with Lettuce
As beginners
We’ll implement factorial

Scenario: Factorial of 0
Given I have the number 0
When I compute its factorial
Then I see the number 1

Scenario: Factorial of 1
Given I have the number 1
When I compute its factorial
Then I see the number 1

Scenario: Factorial of 2
Given I have the number 2
When I compute its factorial
Then I see the number 2

Scenario: Factorial of 3
Given I have the number 3
When I compute its factorial
Then I see the number 6

BDD(Behavier Driven Data)使用多条用例,模拟数据库,类似于一个查询的操作
文件存储地方:
E:\PythonDemo\Glory\201902242\features
step.py

#encoding=utf-8
from lettuce import *@step('I have the following students in my database:')
def students_in_database(step):if step.hashes:# 如果存在步骤表格数据,则继续后续步骤print type(step.hashes)assert step.hashes == [{'name': 'Anton','monthly_due': '$ 500','billed': 'no'},{'name': 'Jack','monthly_due': '$ 400','billed': 'no'},{'name': 'Gabriel','monthly_due': '$ 300','billed': 'no'},{'name': 'Gloria','monthly_due': '$ 442.65','billed': 'no'},{'name': 'Ken','monthly_due': '$ 907.86','billed': 'no'},{'name': 'Leonard','monthly_due': '$ 742.84','billed': 'no'},]@step('I bill names starting with "(.*)"')
def match_starting(step, startAlpha):# 将通过正则表达式匹配步骤中最后一个字母,# 并存于全局变量startAlpha中world.startAlpha = startAlphaprint "no data exist:",step.hashes@step('I see those billed students:')
def get_starting_with_G_student(step):# 遍历步骤数据表中的数据for i in step.hashes:# 断言学生的名字是否以world.startAlpha变量存取的的字母开头assert i["name"].startswith(world.startAlpha)@step("those that weren't:")
def result(step):for j in step.hashes:# 断言学生名字不以world.startAlpha变量存取的的字母开头# 断言学生名字不以world.startAlpha变量存取的的字母开头assert world.startAlpha not in j["name"][0]

student.feature
Feature: bill students alphabetically
In order to bill students properly
As a financial specialist
I want to bill those which name starts with some letter

Scenario: Bill students which name starts with "G"
Given I have the following students in my database:| name     | monthly_due | billed || Anton    | $ 500       | no     || Jack     | $ 400       | no     || Gabriel  | $ 300       | no     || Gloria   | $ 442.65    | no     || Ken      | $ 907.86    | no     || Leonard  | $ 742.84    | no     |
When I bill names starting with "G"
Then I see those billed students:| name     | monthly_due | billed || Gabriel  | $ 300       | no     || Gloria   | $ 442.65    | no     |
And those that weren't:| name     | monthly_due | billed || Anton    | $ 500       | no     || Jack     | $ 400       | no     || Ken      | $ 907.86    | no     || Leonard  | $ 742.84    | no     |

sougou.feature
行为驱动 + webdriver + 数据驱动的例子
terrain 装饰器 自动执行 做准备 做清理
前提条件 :
py -2 -m pip install selenium
sogou.feature
sogou.py
terrain.py

sogou.feature
Feature: Search in Sogou website
In order to Search in Sogou website
As a visitor
We’ll search the NBA best player

Scenario: Search NBA player
Given I have the english name “<search_name>”
When I search it in Sogou website
Then I see the entire name “<search_result>”

Examples:
| search_name | search_result |
| Jordan | Michael |
| Curry | Stephen |
| Kobe | Bryant |

sogou.py

#encoding=utf-8
from lettuce import *
from selenium import webdriver
import time@step('I have the english name "(.*)"')
def have_the_searchWord(step, searchWord):world.searchWord = str(searchWord)print world.searchWord@step('I search it in Sogou website')
def search_in_sogou_website(step):world.driver = webdriver.Ie(executable_path = "d:\\chromedriver.exe")world.driver.get("http://www.sogou.com")world.driver.find_element_by_id("query").send_keys(world.searchWord)world.driver.find_element_by_id("stb").click()time.sleep(3)@step('I see the entire name "(.*)"')
def check_result_in_sogou(step, searchResult):assert searchResult in world.driver.page_source, "got word:%s" %searchResultworld.driver.quit()

terrain.py

#encoding=utf-8
from lettuce import *
import logging#初始化日志对象
logging.basicConfig(# 日志级别level = logging.INFO,# 日志格式# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt = '%a, %Y-%m-%d %H:%M:%S',# 日志文件存放的目录(目录必须存在)及日志文件名filename = 'e:/BddDataDriveRreport.log',# 打开日志文件的方式filemode = 'w'
)
#在所有场景执行前执行
@before.all
def say_hello():logging.info("Lettuce will start to run tests right now...")print "Lettuce will start to run tests right now..."#在每个secnario开始执行前执行
@before.each_scenario
def setup_some_scenario(scenario):# 每个Scenario开始前,打印场景的名字print 'Begin to execute scenario name:' + scenario.name# 将开始执行的场景信息打印到日志logging.info('Begin to execute scenario name:' + scenario.name)#每个step开始前执行
@before.each_step
def setup_some_step(step):run = "running step %r, defined at %s" % (step.sentence, # 执行的步骤step.defined_at.file # 步骤定义在哪个文件)# 将每个场景的每一步信息打印到日志logging.info(run)#每个step执行后执行
@after.each_step
def teardown_some_step(step):if not step.hashes:print "no tables in the step"   #会被打印9次,因为我们仅仅设定了场景的table,而不是给每个步骤设定table#注意每个step可以有自己的table,等价于把table的数据作为一个字典传入到程序中使用。logging.info("no tables in the step")#在每个secnario执行结束执行
@after.each_scenario
def teardown_some_scenario(scenario):print  'finished, scenario name:' + scenario.namelogging.info('finished, scenario name:' + scenario.name)#在所有场景开始执行后执行
@after.all #默认获取执行结果的对象作为total参数
def say_goodbye(total):result = "Congratulations, %d of %d scenarios passed!" % (total.scenarios_ran,  #一共多少场景运行了total.scenarios_passed #一共多少场景运行成功了)print resultlogging.info(result)# 将测试结果写入日志文件logging.info("Goodbye!")print "------ Goodbye! ------"

基于中文的行为驱动:中文feature
baidu.feature
terrain.py
log.py
baidu.feature
在默认编码为GBK的Windows系统中执行场景使用中文描述的行为驱动测试时,打印到控制台的场景等信息,中文会出现乱码,这是由于lettuce框架将输出到控制台的场景描述信息转成UTF8编码的字符导致的。下面针对lettuce(0.2.23)版本给出具体解决方法。
(1)进入Python安装目录中lettuce安装路径中的plugins目录中,
比如本地路径为C:\Python27\Lib\site-packages\lettuce\plugins。
(2)找到该目录下的colored_shell_output.py文件,
(3)打开该文件,找到该文件的第32行代码what = what.encode(‘utf-8’)
,将其改成what = what#.encode(‘utf-8’)

程序见 E:\PythonDemo\Glory\201902244\features

baidu.feature
#encoding=utf-8
#language: zh-CN

特性: 在百度网址搜索IT相关书籍
能够搜索到书的作者,比如吴晓华

场景: 在百度网站搜索IT相关书籍如果将搜索词设定为书的名字"<书名>"当打开百度网站和在搜索输入框中输入搜索的关键词,并点击搜索按钮后那么在搜索结果中可以看到书的作者"<作者>"例如:| 书名                         | 作者   || Selenium WebDriver实战宝典   | 吴晓华 || HTTP权威指南                 | 协议 || Python核心编程               | Python |

terrain.py

#encoding=utf-8
from lettuce import *
from log import *#在所有场景执行前执行
@before.all
def say_hello():logging.info(u"开始执行行为数据驱动测试...")#在每个secnario开始执行前执行
@before.each_scenario
def setup_some_scenario(scenario):# 将开始执行的场景信息打印到日志logging.info(u'开始执行场景“%s”' %scenario.name)#每个step开始前执行
@before.each_step
def setup_some_step(step):world.stepName = step.sentencerun = u"执行步骤“%s”, 定义在“%s”文件" % (step.sentence, # 执行的步骤step.defined_at.file # 步骤定义在哪个文件)# 将每个场景的每一步信息打印到日志logging.info(run)#每个step执行后执行
@after.each_step
def teardown_some_step(step):logging.info(u"步骤“%s”执行结束" % world.stepName)#在每个secnario执行结束执行
@after.each_scenario
def teardown_some_scenario(scenario):logging.info(u'场景“%s”执行结束' %scenario.name)#在所有场景开始执行后执行
@after.all #默认获取执行结果的对象作为total参数
def say_goodbye(total):result = u"恭喜,%d个场景运行,%d个场景运行成功" % (total.scenarios_ran,  #一共多少场景运行了total.scenarios_passed #一共多少场景运行成功了)logging.info(result)# 将测试结果写入日志文件logging.info(u"本次行为数据驱动执行结束")

log.py

#encoding=utf-8
import logging#初始化日志对象
logging.basicConfig(# 日志级别level = logging.INFO,# 日志格式# 时间、代码所在文件名、代码行号、日志级别名字、日志信息format = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',# 打印日志的时间datefmt = '%a, %Y-%m-%d %H:%M:%S',# 日志文件存放的目录(目录必须存在)及日志文件名filename = 'e:/BddDataDriveRreport.log',# 打开日志文件的方式filemode = 'w'
)

批量执行多个feature
E:\PythonDemo\Glory\201902245\features
中英文 文件
d:\chromedriver.exe
演示示例所需文件如下:
Login_Chinese.feature
Login_Chinese.py
Login_English.feature
Login_English.py
terrain.py

Login_Chinese.feature
#encoding=utf-8
#language: zh-CN

特性: 登录126邮箱和退出126邮箱登录

场景: 成功登录126邮箱假如启动一个浏览器当用户访问http://mail.126.com网址当用户输入输入用户名“axu28990@126.com”和对应的邮箱密码那么页面会出现“未读邮件”关键字场景: 成功退出126邮箱当用户从页面单击退出链接那么页面显示“您已成功退出网易邮箱”关键内容

Login_Chinese.py

#encoding=utf-8
#language: zh-CN
from lettuce import *
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time@step(u'启动一个浏览器')
def open_browser(step):try:# 创建Chrome浏览器的driver实例,并存于全局对象world中,# 供后续场景或步骤函数使用world.driver = webdriver.Chrome(executable_path = "d:\\chromedriver.exe")except Exception, e:raise e@step(u'用户访问(.*)网址')
def visit_url(step, url):print urlworld.driver.get(url)@step(u'用户输入输入用户名“(.*)”和密码“(.*)”')
def user_enters_UserName_and_Password(step, username, password):print username, password# 浏览器窗口最大化world.driver.maximize_window()time.sleep(3)# 切换进frame控件world.driver.switch_to.frame(world.driver.find_element_by_xpath("//iframe[contains(@id,'x-URS-iframe')]"))# 获取用户名输入框userName = world.driver.find_element_by_xpath('//input[@name="email"]')userName.clear()# 输入用户名userName.send_keys(username)# 获取密码输入框pwd = world.driver.find_element_by_xpath("//input[@name='password']")# 输入密码pwd.send_keys(password)# 发送一个回车键pwd.send_keys(Keys.RETURN)# 等待15秒,以便登录后成功进入登录后的页面time.sleep(15)@step(u'页面会出现“(.*)”关键字')
def message_displayed_Login_Successfully(step, keywords):# print world.driver.page_source.encode('utf-8')# 断言登录成功后,页面是否出现预期的关键字assert keywords in world.driver.page_source# 断言成功后,打印登录成功信息print "Login Success"@step(u'用户从页面单击退出链接')
def LogOut_from_the_Application(step):print "====",world.driver# time.sleep(5)# 点击退出按钮,退出登录world.driver.find_element_by_link_text(u"退出").click()time.sleep(8)@step(u'页面显示“(.*)”关键内容')
def displayed_LogOut_Successfully(step, keywords):# 断言退出登录后,页面是否出现退出成功关键内容assert keywords in world.driver.page_sourceprint u"Logout Success"# 退出浏览器world.driver.quit()

Login_English.feature
#encoding=utf-8

Feature: login and logout

Scenario: Successful Login with Valid Credentials
Given Launch a browser
When User visit to http://mail.126.com Page
And User enters UserName"axu28990" and Password"邮箱对应密码"
Then Message displayed Login Successfully

Scenario: Successful LogOutWhen User LogOut from the ApplicationThen Message displayed LogOut Successfully

Login_English.py

#encoding=utf-8
from lettuce import *
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time@step('Launch a browser')
def open_browser(step):try:world.driver =  webdriver.Chrome(executable_path = "d:\\chromedriver.exe")except Exception, e:raise e@step('User visit to (.*) Page')
def visit_url(step, url):world.driver.get(url)@step('User enters UserName"(.*)" and Password"(.*)"')
def user_enters_UserName_and_Password(step, username, password):world.driver.maximize_window()time.sleep(3)world.driver.switch_to.frame(world.driver.find_element_by_xpath('//iframe[contains(@id,"x-URS-iframe")]'))userName = world.driver.find_element_by_xpath('//input[@name="email"]')userName.clear()userName.send_keys(username)pwd = world.driver.find_element_by_xpath("//input[@name='password']")pwd.send_keys(password)pwd.send_keys(Keys.RETURN)time.sleep(15)@step('Message displayed Login Successfully')
def message_displayed_Login_Successfully(step):# print world.driver.page_source.encode('utf-8')assert u"未读邮件" in world.driver.page_sourceprint "Login Success"@step('User LogOut from the Application')
def LogOut_from_the_Application(step):print "====",world.driver# time.sleep(15)world.driver.find_element_by_partial_link_text(u"退出").click()time.sleep(4)@step('Message displayed LogOut Successfully')
def displayed_LogOut_Successfully(step):assert u"您已成功退出网易邮箱" in world.driver.page_sourceprint u"Logout Success"world.driver.quit()

terrain.py

#encoding=utf-8
from lettuce import *#在所有场景执行前执行
@before.all
def say_hello():print u"开始执行行为数据驱动测试..."#在每个secnario开始执行前执行
@before.each_scenario
def setup_some_scenario(scenario):print u'开始执行场景“%s”' %scenario.name#在每个secnario执行结束后执行
@after.each_scenario
def teardown_some_scenario(scenario):print u'场景“%s”执行结束' %scenario.name#在所有场景执行结束后执行
@after.all #默认获取执行结果的对象作为total参数
def say_goodbye(total):result = u"恭喜,%d个场景被运行,%d个场景运行成功" % (total.scenarios_ran,  #一共多少场景运行了total.scenarios_passed #一共多少场景运行成功了)print result

行为驱动python相关推荐

  1. python硬件驱动_硬件驱动python

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! linux获取linux硬件信息的方式,有很多. 1.使用puppet或者sal ...

  2. 案例驱动python编程入门-用Python进行行为驱动开发的入门教程

    为驱动开发(Behavior-Driven Development,BDD)是一种卓越的开发模式.能帮助开发者养成日清日结的好习惯,从而避免甚至杜绝"最后一分钟"的情况出现,因此对 ...

  3. 案例驱动python编程入门-python ddt数据驱动实例代码分享

    python ddt数据驱动最简实例 在接口自动化测试中,往往一个接口的用例需要考虑 正确的.错误的.异常的.边界值等诸多情况,然后你需要写很多个同样代码,参数不同的用例.如果测试接口很多,不但需要写 ...

  4. 案例驱动python编程入门-事件驱动程序

    事件驱动程序侧重于事件. 最终,程序的流程取决于事件. 到目前为止,我们正在处理顺序或并行执行模型,但具有事件驱动编程概念的模型称为异步模型. 事件驱动的编程依赖于一直监听新来的事件的事件循环. 事件 ...

  5. 案例驱动python编程入门-Python程序设计任务驱动式学习教程

    本书内容翔实,结构合理,语言精练,表述清晰,实用性强,易于自学,主要内容包括搭建环境和运行Python应用程序.Python基本语法.Python流程控制.列表与元组.函数与模块.文件.面向对象编程. ...

  6. 案例驱动python编程入门-python实现事件驱动

    本文实例为大家分享了python实现事件驱动的具体代码,供大家参考,具体内容如下 EventManager事件管理类实现,大概就百来行代码左右. # encoding: UTF-8 # 系统模块 fr ...

  7. 树莓派控制3631AS数码管 驱动 python程序 共阴数码管|徐奥雯编写|XUAOWEN

    使用方法: 新建py文件,将下面的驱动代码复制到文件中保存,命名为drive_3631as.py 连接树莓派与数码管 根据上面的引脚图的1-12号(没有6) 所连接树莓派的GPIO引脚,在刚刚新建的d ...

  8. 案例驱动python编程入门-郑州高薪python全栈工程师

    阶段一.Python 全栈工程师之必知必会 - 前端开发技术 课程一.入门必备 - 新手学 HTML5+CSS3 1.HTML基本标签 2.W3C标准及XHTML1.0基本规范 3.表格.表单及框架 ...

  9. 案例驱动python编程入门-python监听socket客户端连接(驱动串口屏幕)

    [实例简介] [实例截图] [核心代码] import socket import os import sys import struct def socket_service_data(): try ...

最新文章

  1. 一起谈.NET技术,Visual Studio 2010 中的代码约定设置
  2. 通过WebRTC实现实时视频通信(三)
  3. Java设计模式之(工厂模式)--简单工厂模式--工厂方法模式--抽象工厂模式
  4. 【spider】多线程爬虫
  5. Java双端队列Deque及其应用
  6. 首份“中国大数据的社会经济价值研究报告”发布
  7. 原始图片中的ROI如何映射到到feature map?(转)
  8. Centos7 安装MySQL5
  9. 安装多个 PHP 版本(PHP7, PHP5)
  10. 【历史上的今天】8 月 21 日:谷歌创始人诞生;百度 360 搜索大战
  11. WPS文档如何删除空白页
  12. #bzoj1526#分梨子(乱搞)
  13. 嵌入式SQLite数据库架构和设计
  14. 未来简史--读书语句摘录及感悟
  15. 短视频平台类的社交媒体市场现状与发展前景到底如何?
  16. 怎么在b站引流?b站怎么吸粉?b站引流技巧和方法
  17. 【Python】python爬取百度云网盘资源-源码
  18. uni-app 超好用的时间选择器组件(起止时间)
  19. Visio绘制跨职能流程图示例
  20. python throw_python 之 异常处理

热门文章

  1. 超级实时图形计算机,从猫狗不分到实时识别准确率超过99%,计算机图像识别是如何做到的?...
  2. sqliteconnection中的version一旦比先前的大,则执行onUpgrade;模仿疯狂猜图游戏;matrix设置图片比例
  3. 基于VB的产品追溯系统——运营管理制胜关键
  4. 【Linux】进程控制 — 进程终止 + 进程等待
  5. 专家汇 | 车联网这样上云,真的很酷!
  6. 好程序员大数据教程分享超详细大数据学习路线
  7. 奇虎360:免费安全软件龙头
  8. Python 程序扩展名(py, pyc, pyw, pyo, pyd)及发布程序时的选择
  9. 学习笔记——面向对象第三天
  10. 光伏储能并网发电模型,根据储能电池SOC的工作区间,光伏有MPPT、恒功率输出两种控制方式,在电池健康工况下光伏处于MPPT模式