zoukankan      html  css  js  c++  java
  • BDD行为驱动简介及Pytest-bdd基础使用


    pytest-bdd.png

    运行环境: pip insall pytest pytest-bdd pytest-selenium

    BDD介绍

    BDD行为驱动是一种敏捷开发模式, 重点在于消除开发/测试对需求了解的歧义及用户场景的验证.

    需求描述/用户场景

    BDD提供一套标准的需求及用户场景表达语法, 一般为Feature(需求), Scenario(场景), Given(假设,预置条件), When(操作步骤), Then(验证及清理), 如下为一个需求描述(有的公司称为需求卡片):

    文件名: educa.feature 需求使用专门的.feature作为后缀

    Feature: educa在线课程网站需求
        需求描述: 提供后台添加课程及课程内容, 前台学生浏览课程, 加入课程后可查看课程详情
    
    Scenario: 通过educa后台添加课程
        Given 用户:hanzhichao, 密码:hanzhichao123
        And 分类:接口测试,标题:Python接口测试教程,描述:作者,临渊
        When 登录educa后台
        And 点击:Courses模块->点击新增按钮
        And 作者选择当前<用户>,选择<分类>,输入<标题>,<描述>,点击保存
        Then 页面中应存在名称为<标题>的链接
        And 删除该课程
    
    #Scenario: 学生选课
    #    ...
    

    • 一个需求文件中只能有一个Feature字段, 可以包含多个Scenario(用户场景)
    • Given->When->Then类似与准备->执行->验证/清理的流程
    • Given: 一般可以用来做预置条件/数据准备, 下面第一个And也属于Given
    • When下面的量And都属于When, 一般是操作步骤, <用户>等只是用来提醒使用的是Given中的数据, 也可以不使用<>
    • Then: 一般用于验证结果(断言), 也可以进行清理数据

    场景解析/实现

    单有场景文件是不能执行的, 在BDD的初级使用中, 测试同学还需要将每个场景文件中的描述翻译成具体的页面操作, 每一句对应一个函数, 下面是使用pytest-bdd对上诉educt.feature的解析实现:

    # file_name: scenario_steps.py
    from pytest_bdd import given, when, then, parsers  
    from selenium.webdriver.support.select import Select
    from selenium.webdriver.support import expected_conditions as EC
    
    
    @given(parsers.parse("用户:{username}, 密码:{password}"))
    def user(username, password):  # 类似一个pytest的fixture方法, 其他步骤可以使用其返回值
        return dict(username=username, password=password)
    
    
    @given(parsers.parse("分类:{category},标题:{title},描述:{description}"))
    def course(category, title, description):
        return dict(category=category, title=title, description=description)
    
    
    @when("登录educa后台")  # 固定操作,不需要获取参数则不用parsers.parse()
    def login(selenium, user):  # 使用上面user函数的返回数据, selenium为浏览器driver(来着:pytest-selenium)
        selenium.get("http://qaschool.cn:8000/admin/")
        selenium.find_element_by_id("id_username").send_keys(user['username'])
        selenium.find_element_by_id("id_password").send_keys(user['password'])
        selenium.find_element_by_class_name("submit-row").click()
    
    
    @when(parsers.parse("点击:{module}模块->点击新增按钮"))
    def add_course(selenium, module):
        selenium.find_element_by_link_text(module).click()  # 点击'Courses'链接
        selenium.find_element_by_class_name("addlink").click()  # 点击'新增 COURSE'按钮
    
    
    @when("作者选择当前<用户>,选择<分类>,输入<标题>,<描述>,点击保存")  # 也可以不使用<>, 要与场景中一致, 使用<>只是提示是从Given的数据中获取
    def edit_course(selenium, user, course):  # 使用上面course函数的返回数据
        Select(selenium.find_element_by_id("id_owner")).select_by_visible_text(user['username'])  # 选择作者
        Select(selenium.find_element_by_id("id_subject")).select_by_visible_text(course['category'])  # 选择主题
        selenium.find_element_by_id("id_title").send_keys(course['title'])  # 输入文章标题
        selenium.find_element_by_id("id_overview").send_keys(course['description'])  # 输入描述
        selenium.find_element_by_class_name("default").click()  # 点击保存
    
    
    @then("页面中应存在名称为<标题>的链接")
    def check_course(course):
        assert EC.presence_of_element_located(("link text", course['title']))
    
    
    @then("删除该课程")
    def delete_course(selenium, course):
        selenium.find_element_by_link_text(course['title']).click()
        selenium.find_element_by_class_name("deletelink").click()
        selenium.find_element_by_css_selector("input[type='submit']").click()
    
    

    • parsers用于解析语句中的参数
    • 方法中的selenium参数为使用pytest-selenium中的浏览器driver, 固定参数名
    • EC.presence_of_element_located用来验证可定位到元素

    场景测试

    # file_name: test_educa.py
    from pytest_bdd import scenario
    from scenario_steps import *  # 导入场景解释/支持步骤
    
    @scenario("educa.feature", "通过educa后台添加课程")   
    def test_add_course():  # 测试educa需求文件中名为"通过educa后台添加课程"的场景
        pass   # 可以不写内容, pass即可
    
    

    • 场景测试也可以和场景实现写到一起

    执行测试

    使用pytest-selenium执行用例是需要指定浏览器
    在test_educa.py所在目录命令行中执行:

     pytest test_educa.py --driver Chrome
    

    Pytest-bdd的参数化

    待补充...

    注: 上文提到BDD的初级使用,是因为这是一种被动的测试模式, 每一个不同的需求卡片的每一句都需要去进行解释实现, 其中有大量的重复性工作, 另外缺乏开发的参与与支持.
    除了部分程度上, 消除测试同学需求理解的歧义性及让测试同学更注重用户场景的验证而不是开发(功能点)逻辑的验证外, 这基本上跟写selenium自动化脚本一样, 由于场景解释脚本的不稳定而耗费大量的工作无法发现有价值的问题

    BDD行为驱动的最佳实践,请见下回分解...

  • 相关阅读:
    云级Keyvalue数据库大比较
    如何诊断ORA125XX连接问题
    Oracle Internal Event:10235 Heap Checking诊断事件
    Oracle Database 11g R2 在Oracle Linux 6上获得认证
    一张图帮你搞懂oracle UGA User Global Area的概念
    Oracle Buffer Cache Chain图解
    ORA04036: 实例使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT
    如何诊断ASMLIB故障
    Oracle RDBMS Server 11gR2 Preinstall RPM For Oracle Linux 6
    图解Oracle Buffer Cache LRU List
  • 原文地址:https://www.cnblogs.com/superhin/p/11454716.html
Copyright © 2011-2022 走看看