为什么要进行框架封装

  1. 定位等待之类细枝末节的事情
  2. UI 操作代码需要可重用
  3. 对测试用例 分类、筛选、管理

POM 框架封装

pomUI 自动化测试一种主流的设计模式

page object model 页面对象模式

将页面作为对象模型,来进行框架封装:

  1. 创建:这个 代表 页面

  2. 定义属性:这些属性 代表 页面中的元素

    1
    2
    LazyElement()	   # 定位单个元素
    LazyElementList() # 定位多个元素
  3. 定义方法:这些个方法 代表 对页面的操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    import time
    from webdriver_helper import get_webdriver
    from webdriver_helper.pom import *


    class IndexPage(BasePage):
    """首页"""

    # 定位到搜索框
    ipt_indexPage = LazyElement(By.XPATH, '//*[@id="key"]')
    # 定位到搜索按钮
    btn_searchPage = LazyElement(
    By.XPATH, '//*[@id="search"]/div/div[2]/button')

    def search(self, wd) -> 'SearchPage':
    """
    搜索关键词
    :param wd: 关键词,如:手机
    :return: 搜索结果
    """
    # 输入内容
    self.ipt_indexPage.send_keys(wd)
    # 点击 搜索结果
    self.btn_searchPage.click()

    return SearchPage(self.driver)


    class SearchPage(BasePage):
    """搜索页面"""

    # //*[@id="J_goodsList"]/ul/li[2]/div/div[4]/a/em
    # //*[@id="J_goodsList"]/ul/li[3]/div/div[4]/a/em
    # //*[@id="J_goodsList"]/ul/li[4]/div/div[4]/a/em
    p_title_list = LazyElementList(
    By.XPATH, '//*[@id="J_goodsList"]/ul') # 同时定位 N 个元素

    def get_all_titles(self) -> list[str]:
    l = []
    for p in self.p_title_list:
    l.append(p.text) # 将所有元素的文本,加入的列表

    return l


    if __name__ == '__main__':
    driver = get_webdriver() # 默认使用Google chrome,如需要用 Firefox,在括号内加入
    driver.get("https://www.jd.com/") # 被测页面
    driver.maximize_window() # 窗口最大化
    time.sleep(3) # 强制等待
    index_page = IndexPage(driver) # 点击搜索框
    search_page = index_page.search("手机") # 输入文字
    time.sleep(3)

    title_list = search_page.get_all_titles()
    for title in title_list:
    print(title)
    assert "手机" in title # 断言

pytest测试框架

引入pytest测试框架

  1. 安装

    1
    pip install pytest

    这里还有一篇关于pytest测试框架的安装和介绍 Pytest介绍和教程,多扩展一些知识,

  2. 编写测试用例

    • test_开头的文件

    • test_开头的函数 (或者 Test 开头的类)

    • 在用例中使用断言

      1
      2
      3
      4
      # test_abc.py

      def test_bcd():
      assert 1 == 2
  3. 执行用例

    • pytest
    • python-m
    • pytest.main()
  4. 结果释义

    结果缩写符号
    符号含义
    .通过
    F失败
    E出错
    XXPass 意外通过(预期失败,结果成功==不符合预期)
    xxfailed 预期失败(预期失败,结果失败==符合预期)
  5. pytest高级用法

    浏览器重复启动,消耗较多的时间,写法繁琐也不美观。

    相似的用例,需要复制粘贴,不能用之前的代码。

    不推荐使用此代码方式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    from webdriver_helper import get_webdriver
    from pom import IndexPage

    def test_demo02():
    assert "北凡" == "小冰"

    def test_web_search_a():
    driver = get_webdriver()
    driver.get("https://www.jd.com/")
    index_page = IndexPage(driver) # 实例化page 定位到搜索框
    search_page = index_page.search("手机") # 输入内容

    title_list = search_page.get_all_title()
    for title in title_list:
    print(title)
    assert "手机" in title

    def test_web_search_b():
    driver = get_webdriver()
    driver.get("https://www.jd.com/")
    index_page = IndexPage(driver)
    search_page = index_page.search("冰箱")

    title_list = search_page.get_all_title()
    for title in title_list:
    print(title)
    assert "冰箱" in title

    可以在测试用例之前、之后、自动执行代码,一般用于准备测试环境,构造测试数据,清理测试现场。

    web测试的前置条件:启动浏览器

    web测试的后置条件:关闭浏览器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from webdriver_helper import get_webdriver
    import pytest

    @pytest.fixture
    def driver():
    d = get_webdriver() # 前置操作

    yield d # 区分前后置

    d.quit() # 后置操作

    fixturepytest

    装饰器 是 python

    fixture可以在用例之间共享解决重复的前置和后置操作

    fixture的共享范围 有5个级别:

    • function 默认值 不共享

    • class

    • module(文件)

    • package(文件夹)

    • session 全局共享

      1
      2
      3
      4
      5
      6
      7
      @pytest.fixture(scope='module') # 有了这 fixture 装饰器之后,成为了 fixture
      def driver():
      d = get_webdriver() # 前置操作

      yield d # 区分前后置

      d.quit() # 后置操作

      对于相识的测试用例,通过参数测试,传递不通的部分,可以实现复用测试用例代码。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @pytest.mark.parametrize("wd",["手机","冰箱"])
      def test_web_search(driver,wd):
      driver.get("https://www.jd.com/")
      index_page = IndexPage(driver) # 实例化page 定位到搜索框
      search_page = index_page.search(wd) # 输入内容

      title_list = search_page.get_all_title()
      for title in title_list:
      print(title)
      assert wd in title