• 行为驱动(2)


    行为驱动(2)
    5、lettuce框架的步骤数据表格
    实例:
    (1)在PyCharm工具中创建如下所示的目录结构及文件
    ..lettuceStepDataTablesfeaturesstudent.features
    ..lettuceStepDataTablesfeaturessteps.py
    (2)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     |

    Given、Then及And步骤下都存在步骤数据表格,数据间以“|”进行分隔,数据表的第一行表示数据表的列名,不作为数据存在。
    (3)steps.py文件,用于编写获取student.feature文件中的数据,并提供后续操作,具体内容如下:

    #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 = startAlpha
        print 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变量存取的的字母开头
            assert world.startAlpha not in j["name"][0]

    6、 使用WebDriver进行英文语言的行为数据驱动测试
    测试逻辑:
    (1)访问http://www.sogou.com
    (2)依次搜索几个球星的英文名字中的一部分
    (3)在搜索结果页面断言搜索的球星的全名

    实例:
    (1)在PyCharm工具中创建如下所示的目录结构及文件:
    ..lettuceBddDataDrivenByEnglishfeaturessogou.feature
    ..lettuceBddDataDrivenByEnglishfeaturessogou.py
    ..lettuceBddDataDrivenByEnglishfeatures errain.py
    (2)sogou.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    |

    Examples下面是一个场景数据表,数据间以“|”进行分隔,数据表的第一行表示数据表的列名,与场景中的变量名对应,比如Given I have the english name "<search_name>"语句中的search_name对应数据表中的search_name列
    (3)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.Firefox(executable_path = "D:\geckodriver")
        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" % searchResult
        world.driver.quit()

    (4)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 = "D:\PythonProject\BDD\lettuce\BddDataDrivenByEnglish\BddDataDrivenReport.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..."
    
    #在每个Scenario开始执行前执行
    @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,defind at % s" % (
            step.sentence, #执行的步骤
            step.defined_at.file #步骤定义在哪个文件
        )
        #将每个场景的每一步信息打印到日志
        logging.info(run)
    
    #每个step执行后执行
    @after.each_step
    def teardown_some_step(step):
        logging.info("End of the:'%s'" % step.sentence)
    
    #在每个Scenario执行结束执行
    @after.each_scenario
    def teardown_some_scenario(scenario):
        print "Finished,scenario name: " + scenario.name
        logging.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 result
        #将测试结果写入日志文件
        logging.info(result)
        logging.info("Goodbye!")
        print "------------Goodbye!-------------"

    7、使用WebDriver进行中文语言的行为数据驱动测试
    测试逻辑:
    (1)访问 http://www.baidu.com
    (2)依次搜索几本中文名字的书
    (3)在搜索结果页面断言是否出现书的预期作者
    实例:
    (1)在PyCharm工具中创建如下所示的目录结构及文件
    ..lettuceBddDataDrivenByChinesefeaturesaidu.feature
    ..lettuceBddDataDrivenByChinesefeaturesaidu.py
    ..lettuceBddDataDrivenByChinesefeatures errain.py
    ..lettuceBddDataDrivenByChinesefeatureslog.py
    (2)baidu.feature文件内容如下:

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

    (3)baidu.py文件内容如下:

    #encoding=utf-8
    #language:zh-CN
    from lettuce import *
    from selenium import webdriver
    import time
    
    @step(u'将搜索词设定为书的名字"(.*)"')
    def have_the_searchWord(step,searchWord):
        world.searchWord = searchWord
        print world.searchWord
    
    @step(u'打开百度网站')
    def visit_baidu_website(step):
        world.driver = webdriver.Firefox(executable_path = "D:\geckodriver")
        world.driver.get("http://www.baidu.com")
    
    @step(u'在搜索输入框中输入搜索的关键词,并点击搜索按钮后')
    def search_in_sogou_website(step):
        world.driver.find_element_by_id("kw").send_keys(world.searchWord)
        world.driver.find_element_by_id("su").click()
        time.sleep(3)
    
    @step(u'在搜索结果中可以看到书的作者"(.*)"')
    def check_result_in_sogou(step,searchResult):
        assert searchResult in world.driver.page_source , "not got words: %s" % searchResult
        world.driver.quit()

    (4)terrain.py文件内容如下:

    #encoding=utf-8
    from lettuce import *
    from log import *
    
    #在所有场景执行前执行
    @before.all
    def say_hello():
        logging.info(u"开始执行行为数据驱动测试...")
    
    #在每个scenario开始前执行
    @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.sentence
        run = 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)
    
    #在每个scenario执行结束后执行
    @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'本次行为数据驱动执行结束')

    (5)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 = "D:\PythonProject\BDD\lettuce\BddDataDrivenByChinese\BddDataDrivenReport.log",
        #打开日志的方式
        filemode = "w"
    )

    Lettuce支持中文语言编写的测试场景,是通过在场景文件以及测试场景的脚本文件的顶部添加# language:zh-CN,声明使用的语言为中文,同时,feature文件的编码必须保存为utf-8

    8、批量执行行为驱动用例集
    lettuce支持一次执行多个用例,也就是放到features目录下的多个.feature文件。
    实例:
    在PyCharm工具中创建如下所示的目录结构及文件
    ..lettuceMultipleFeaturesfeatureLogin_Chinese.feature
    ..lettuceMultipleFeaturesfeatureLogin_Chinese.py
    ..lettuceMultipleFeaturesfeatureLogin_English.feature
    ..lettuceMultipleFeaturesfeatureLogin_English.py
    ..lettuceMultipleFeatures errain.py

    Login_Chinese.feature文件具体内容如下:

    #encoding=utf-8
    # language: zh-CN
    
    特性: 登录126邮箱和退出126邮箱登录
    
        场景: 成功登录126邮箱
            假如启动一个浏览器
            当用户访问https://mail.126.com网址
            当用户输入用户名“chenyl_2019”和密码“sxzycyl0910”
            那么页面会出现“未读邮件”关键字
    
        场景: 成功退出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.Firefox(executable_path = "D:\geckodriver")
            #浏览器窗口最大化
            world.driver.maximize_window()
            time.sleep(3)
        except Exception,e:
            raise e
    
    @step(u'用户访问(.*)网址')
    def visit_url(step,url):
        print url
        world.driver.get(url)
    
    @step(u'用户输入用户名"(.*)"和密码"(.*)"')
    def user_enters_UserName_and_Password(step,username,password):
        print username,password
        # 点击切换成账号密码登录
        world.driver.find_element_by_id("lbNormal").click()
        time.sleep(1)
        # 找到并切换进iframe控件
        # 目前126和163登录的iframe的id也是动态变化,所以不能用id定位iframe
        iframe = world.driver.find_element_by_xpath('//iframe[contains(@id,"x-URS-iframe")]')
        world.driver.switch_to.frame(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)
        # 退出iframe
        world.driver.switch_to.default_content()
    
    @step(u'页面会出现"(.*)"关键字')
    def message_dispalyed_Login_Successfully(step,keywords):
        #断言登录成功后,页面是否出现预期的关键字
        assert keywords in world.driver.page_source
        #断言成功后,打印登录成功信息
        print "Login Success"
    
    @step(u'用户从页面单击退出链接')
    def LogOut_from_the_Application(step):
        print "==============",world.driver
        #单击退出按钮,退出登录
        world.driver.find_element_by_link_text(u"退出").click()
        time.sleep(3)
    
    @step(u'页面显示"(.*)"关键内容')
    def dispalyed_logOut_Successfully(step,keywords):
        #断言退出登录后,页面是否出现退出成功关键内容
        assert keywords in world.driver.page_source
        print 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"chenyl_2019" and Password"sxzycyl0910"
          Then Message displayed Login Successfully
    
        Scenario: Successful LogOut
            When User LogOut from the Application
            Then 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:
            #创建Chrome浏览器的driver实例,并在于全局对象world中,供后续场景或步骤函数使用
            world.driver = webdriver.Firefox(executable_path = "D:\geckodriver")
            #浏览器窗口最大化
            world.driver.maximize_window()
            time.sleep(3)
        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):
        print username,password
        # 点击切换成账号密码登录
        world.driver.find_element_by_id("lbNormal").click()
        time.sleep(1)
        # 找到并切换进iframe控件
        # 目前126和163登录的iframe的id也是动态变化,所以不能用id定位iframe
        iframe = world.driver.find_element_by_xpath('//iframe[contains(@id,"x-URS-iframe")]')
        world.driver.switch_to.frame(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)
        # 退出iframe
        world.driver.switch_to.default_content()
    
    @step('Message displayed Login Successfully')
    def message_dispalyed_Login_Successfully(step,keywords):
        #断言登录成功后,页面是否出现预期的关键字
        assert u"未读邮件" in world.driver.page_source
        #断言成功后,打印登录成功信息
        print "Login Success"
    
    @step('User LogOut from the Application')
    def LogOut_from_the_Application(step):
        print "==============",world.driver
        #单击退出按钮,退出登录
        world.driver.find_element_by_link_text(u"退出").click()
        time.sleep(3)
    
    @step('Message displayed LogOut Successfully')
    def dispalyed_logOut_Successfully(step,keywords):
        #断言退出登录后,页面是否出现退出成功关键内容
        assert u"您已成功退出网易邮箱" in world.driver.page_source
        print u"Logout Success"
        #退出浏览器
        world.driver.quit()

    terrain.py文件内容用于统计各个场景执行结果信息,具体内容如下:

    #encoding=utf-8
    from lettuce import *
    #在所有场景执行前执行
    @before.all
    def say_hello():
        print u"开始执行行为数据驱动测试..."
    
    #在每个Scenario开始执行前执行
    @before.each_scenario
    def setuo_some_scenario(scenario):
        print u"开始执行场景:'%s'" % scenario.name
    
    #在每个Scenario执行结束后执行
    @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

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

  • 相关阅读:
    锁和监视器之间的区别 – Java并发
    实现Runnable接口和继承Thread类之间的区别
    如何使用wait(), notify() and notifyAll() – Java
    HashMap如何工作
    使用hashCode()和equals()方法
    Compare and Swap [CAS] 算法
    对象级别锁 vs 类级别锁 – Java
    solr的访问权限管理及ubuntu下iptables的设置
    mysql 字符串字段中查找非ascii字符
    tensorflow学习——调试ctc的两个bug
  • 原文地址:https://www.cnblogs.com/test-chen/p/11099729.html
Copyright © 2020-2023  润新知