自动化测试-web(PO:Page Object 模式)

一、PO模式

PO:Page Object(页面对象),将自动化涉及的页面或模块封装成对象。

PO能解决什么问题?

  1. 代码复用性
  2. 便于维护(脚本层与业务分离)--如果元素信息发生变化了,也不用去修改脚本。

PO如何做?

Base层:存放所有页面公共方法

Page层:基于页面或模块单独封装当前页面要操作的对象

Script层:脚本层+unittest

非PO模式的代码实现

import unittest
from selenium import webdriver
from time import sleep

class TestLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
        self.driver.maximize_window()
        self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
        self.driver.implicitly_wait(10)

    def tearDown(self) -> None:
        sleep(5)
        self.driver.quit()

    def test01_login(self):
        self.driver.find_element_by_css_selector("#username").send_keys("13600001111")
        self.driver.find_element_by_css_selector("#password").send_keys("123456")
        self.driver.find_element_by_css_selector("#verify_code").send_keys("8888")
        self.driver.find_element_by_css_selector(".J-login-submit").click()

PO设计结构:

base:存放所有page页面公共方法

page:将页面封装为对象

script:测试脚本

案例:

base.py

"""
base类,存放所有page页面公共操作方法
"""

from selenium.webdriver.support.wait import WebDriverWait

class Base:
    def __init__(self,driver):
        self.driver = driver

    # 查找元素
    def base_find(self,loc,timeout=10,poll_frequency=0.5):
        # 显示等待->查找元素  loc=(By.ID,"#userA")
        return WebDriverWait(self.driver,timeout,poll_frequency).\
            until(lambda x:x.find_element(loc[0],loc[1]))

    # 输入方法
    def base_input(self,loc,value):
        # 获取元素
        el = self.base_find(loc)
        # 清空操作
        el.clear()
        # 输入内容
        el.send_keys(value)

    # 点击方法
    def base_click(self,loc):
        self.base_find(loc).click()

    # 获取文本值方法
    def base_get_text(self,loc):
        return self.base_find(loc).text

page_login.py

"""
模块名:page_模块
类名:大驼峰将模块移植进来,去掉下划线和数字。
方法:自动化测试当前页面要操作哪些元素,就封装哪些方法
"""
from po.base.base import Base
from selenium.webdriver.common.by import By

# 用户名
username = (By.CSS_SELECTOR,"#username")
# 密码
pwd = (By.CSS_SELECTOR,"#password")
# 验证码
verify_code = (By.CSS_SELECTOR,"#verify_code")
# 登录按钮
login_btn = (By.CSS_SELECTOR,".J-login-submit")
# 昵称
nick_name = (By.CSS_SELECTOR,".userinfo")


class PageLogin(Base):
    # 输入用户名
    def __page_username(self,value):
        self.base_input(username,value)
    # 输入密码
    def __page_pwd(self,value):
        self.base_input(pwd,value)
    # 输入验证码
    def __page_verify_code(self,value):
        self.base_input(verify_code,value)
    # 点击登录按钮
    def __page_click_login_btn(self):
        self.base_click(login_btn)
    # 获取昵称
    def page_get_nickname(self):
        return self.base_get_text(nick_name)
    # 组合业务方法(测试业务层调用此方法,便捷)
    def page_login(self,phone,password,code):
        self.__page_username(phone)
        self.__page_pwd(password)
        self.__page_verify_code(code)
        self.__page_click_login_btn()

test_login.py

import unittest
from selenium import webdriver
from po.page.page_login import PageLogin

class TestLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
        self.driver.maximize_window()
        self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
        self.login = PageLogin(self.driver)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_login(self,phone="13600001111",password="123456",code="8888"):
        # 调用登录业务
        self.login.page_login(phone,password,code)
        # 断言
        nickname = self.login.page_get_nickname()
        print("nickname:",nickname)

二、数据驱动

什么是数据驱动?

  • 以测试数据驱动用例执行(测试数据和代码分离)

为什么要数据驱动?

  • 便于维护(维护的焦点从代码转到测试数据)

数据驱动如何操作?

  • 编写数据存储文件
  • 编写读取数据工具
  • 使用参数化引用

编写数据存储文件

  1. 新建json文件,在文件中编写一个{}

  2. 有几个模块,写几个key,值为列表

  3. 列表中参数化数据有几组,就写几个{}

  4. 每个{}中组成: 说明+参数数据+预期结果

    {
    "login":[
    {
    "desc":"登录成功",
    "phone":"13600001111",
    "password":"123456",
    "code":"8888",
    "except_text":"13600001111"
    }
    ]
    }

具体的代码:

json_test.json

{
    "login":[
        {
        "desc":"登录成功",
        "phone":"13600001111",
        "Password":"123456",
        "Code":"8888"
        }
    ]
}

read_json.py

import os
import json

def read_json(filename,key):
    filepath = os.path.dirname(os.path.dirname(__file__)) + os.sep + "data" + os.sep + filename
    arr = []
    with open(filepath,"r",encoding="utf-8") as f:
        for data in json.load(f).get(key):
            arr.append(tuple(data.values())[1:])
        return arr

test_login.py

import unittest
from po_test.page.page_login import PageLogin
from selenium import webdriver
from time import sleep
from parameterized import parameterized
from po_test.util.read_json import read_json

class TestLogin(unittest.TestCase):
    def setUp(self) -> None:
        self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
        self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
        self.driver.maximize_window()
        self.pagelogin = PageLogin(self.driver)

    def tearDown(self) -> None:
        sleep(5)
        self.driver.quit()

    @parameterized.expand(read_json("json_test.json","login"))
    def test_login(self,phone,password,code):
        self.pagelogin.login(phone,password,code)
相关推荐
小白学大数据3 小时前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
程序员小雷1 天前
软件测试基础:单元测试与集成测试
python·功能测试·selenium·测试工具·单元测试·集成测试·压力测试
程序员小雷2 天前
应对自动化测试中的异步操作:策略与实践
功能测试·selenium·测试工具·jmeter·单元测试·测试用例·postman
墨城烟柳Q2 天前
自动化爬虫-selenium模块万字详解
爬虫·python·selenium·自动化
raoxiaoya2 天前
python安装selenium,geckodriver,chromedriver
开发语言·python·selenium
i道i2 天前
python 爬虫 入门 六、Selenium
爬虫·python·selenium
谷隐凡二2 天前
selenium操作已开启的浏览器,方便调试
selenium·测试工具
钱钱钱端3 天前
UI自动化测试 —— CSS元素定位实践!
css·功能测试·selenium·测试工具·jmeter·ui·postman
保护小周ღ3 天前
【Web自动化】探索Selenium与WebDriver的核心原理
selenium·自动化
机器视觉小小测试员3 天前
selenium解决调用Chrome str’ object has no attribute ‘capabilities’ Process finished
chrome·python·selenium