PO模式简介

V1顺序型:不能批量运行

import unittest
from selenium import webdriver
from time import sleep
driver = webdriver.Edge()

# driver.maximize_window()
driver.implicitly_wait(30)
# driver.get(r"https://demo5.tp-shop.cn/")
# driver.find_element_by_partial_link_text("登录").click()

driver.get("https://demo5.tp-shop.cn/Home/user/login.html")

driver.find_element_by_css_selector("#username").send_keys("15217578333")

driver.find_element_by_css_selector("#password").send_keys("123456")

driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
driver.find_element_by_css_selector(".J-login-submit").click()
msg = driver.find_element_by_css_selector(".layui-layer-content").text
print(msg)
assert "账号不存在" == msg
driver.find_element_by_css_selector(".layui-layer-btn0").click()
sleep(2)
driver.quit()
assert "密码不存在" == msg
driver.find_element_by_css_selector(".layui-layer-btn0").click()
sleep(2)
driver.quit()

Unittest:代码冗余 业务脚本与页面对象没有分开

import unittest
from selenium import webdriver
from time import sleep

class TestLogin(unittest.TestCase):
    driver = None
    def tearDown(self):
        self.driver.refresh()

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Edge()
        # driver.maximize_window()
        cls.driver.implicitly_wait(30)
        # cls.driver.get(r"https://demo5.tp-shop.cn/")
        # cls.driver.find_element_by_partial_link_text("登录").click()
        cls.driver.get(r"https://demo5.tp-shop.cn/Home/user/login.html")

    @classmethod
    def tearDownClass(cls):
        sleep(2)
        cls.driver.quit()


    def test_login_username_not_exist(self):
        driver = self.driver

        driver.find_element_by_css_selector("#username").send_keys("15217578333")

        driver.find_element_by_css_selector("#password").send_keys("123456")

        driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
        driver.find_element_by_css_selector(".J-login-submit").click()
        msg = driver.find_element_by_css_selector(".layui-layer-content").text
        print(msg)
        try:
            self.assertEqual("用户不存在", msg)
            driver.find_element_by_css_selector(".layui-layer-btn0").click()
        except AssertionError:
            self.driver.get_screenshot_as_file("../image/not_exist.png")
            # raise

    def test_login_password_err(self):
        driver = self.driver

        driver.find_element_by_css_selector("#username").send_keys("15217578333")

        driver.find_element_by_css_selector("#password").send_keys("123456")

        driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
        driver.find_element_by_css_selector(".J-login-submit").click()
        msg = driver.find_element_by_css_selector(".layui-layer-content").text
        print(msg)
        try:
            self.assertEqual("密码错误",msg)
            driver.find_element_by_css_selector(".layui-layer-btn0").click()
        except AssertionError:
            self.driver.get_screenshot_as_file("../image/error.png")
            # raise

V3 PO page object 冗余代码 耦合性太强

#page

from selenium import webdriver


class PageLogin:
    def __init__(self):
        self.driver = webdriver.Edge()
        # driver.maximize_window()
        self.driver.implicitly_wait(30)
        # driver.get(r"https://demo5.tp-shop.cn/")
        # driver.find_element_by_partial_link_text("登录").click()
        self.driver.get(r"https://demo5.tp-shop.cn/Home/user/login.html")

    # 点击登录
    def page_click_login_link(self):
        pass

    # 输入用户名
    def page_input_username(self,username):
        self.driver.find_element_by_css_selector("#username").send_keys(username)
    # 输入密码
    def page_input_pwd(self,password):
        self.driver.find_element_by_css_selector("#password").send_keys(password)
    # 输入验证码
    def page_input_vertify_code(self,code):
        self.driver.find_element_by_css_selector("#verify_code").send_keys(code)
    # 点击登录
    def page_click_login_btn(self):
        self.driver.find_element_by_css_selector(".J-login-submit").click()
    # 获取异常提示信息
    def page_get_text(self):
        return self.driver.find_element_by_css_selector(".layui-layer-content").text
    # 点击提示框确认按钮
    def page_click_err_btn_ok(self):
        self.driver.find_element_by_css_selector(".layui-layer-btn0").click()

    # 组装业务登录方法、给业务层调用
    def page_login(self,username,password,code):
        self.page_click_login_link()
        self.page_input_username(username)
        self.page_input_pwd(password)
        self.page_input_vertify_code(code)
        self.page_click_login_btn()
#业务层
import unittest
from v3.page.page_login import PageLogin
from  parameterized import parameterized
from time import sleep
class TestLogin(unittest.TestCase):
    def setUp(self):
        # 获取登录页面对象
        self.login = PageLogin()

    def tearDown(self):
        self.login.driver.quit()


    @parameterized.expand([("13822223333","123456","8888","账号不存在"),("13822223333","1236","8888","密码错误")])
    def test_login(self,username,password,code,expect):
        self.login.page_login(username,password,code)
        msg = self.login.page_get_text()
        try:
            self.assertEqual(expect,msg)
            self.login.page_click_err_btn_ok()
        except AssertionError:
            self.login.driver.get_screenshot_as_file("../../image/login_error%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S")))
            # raise

PO page object 页面 对象

V4 三层结构 base page scripts

base(基类)page页面中一些公共的方法 即抽取公共方法放到base中 (提取方法)

新建Base类 初始化方法 查找元素方法 点击元素方法 输入方法 获取文本方法 截图方法(调用数据)

page(页面对象)一个页面封装成一个对象 通过继承base类 使用其中的公共方法(实现使用)

scripts(业务层 脚本层 )导包调用page页面

from selenium.webdriver.common.by import By
loc = (By.CSS_SELECTOR,".telA")
# loc = By.CSS_SELECTOR,".telA" 也是元组类型
# driver.find_element(By.CSS_SELECTOR,".telA")
print(loc)
# 解包
print(*loc)

# ('css selector', '.telA')
# css selector .telA

包和文件夹 包多了init文件

# base
from selenium.webdriver.support.wait import WebDriverWait
import time
from selenium import webdriver
class Base:
    # 临时替代
    # def __init__(self, driver):
    #     self.driver = driver
    def __init__(self):
        self.driver = webdriver.Edge()
        self.driver.get(r"https://demo5.tp-shop.cn/")
    # 解包只需一次 driver传入即可 loc就是查找元素使用的
    # 查找元素方法(提供:点击,输入,获取文本)使用
    def base_find_element(self, loc,timeout=30,poll=0.5):  # loc 元组 *loc进行解包
        # 显示等待
        return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))

    # 点击方法 调用时只需要输入点击哪个元素
    def base_click(self,loc):
        self.base_find_element(loc).click()

    # 输入方法 调用时只需要两个参数 哪个元素 输什么内容
    def base_input(self,loc,value):
        el = self.base_find_element(loc)
        el.clear()
        el.send_keys(value)

    # 获取文本方法 哪个元素文本
    def base_get_text(self,loc):
        # 一定要返回元素的文本信息
        return self.base_find_element(loc).text

    # 截图方法
    def base_get_image(self):
        self.driver.get_screenshot_as_file("../../image/login_error%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S")))
# page init
from selenium.webdriver.common.by import By

# 登录页面元素配置信息 临时存放地
# 登录链接
login_link = By.PARTIAL_LINK_TEXT, "登录"
# 用户名
login_username = By.ID, "username"
# 密码
login_password = By.ID, "password"
# 验证码
login_verify = By.ID, "verify_code"
# 登录按钮
login_btn = By.CSS_SELECTOR, ".J-login-submit"
# 获取异常文本信息
login_err = By.CSS_SELECTOR, ".layui-layer-content"
# 点击异常提示框文本按钮
login_err_btn_ok = By.CSS_SELECTOR, ".layui-layer-btn0"
#page page_login
from v4 import page
from v4.base.base import Base


class PageLogin(Base):
    # 点击登录按钮
    def page_click_login_lin(self):
        self.base_click(page.login_link)

    # 输入用户名
    def page_input_username(self,username):
        self.base_input(page.login_username,username)

    # 输入密码
    def page_input_password(self,password):
        self.base_input(page.login_password,password)

    # 输入验证码
    def page_input_vertfy_code(self,code):
        self.base_input(page.login_verify,code)

    # 点击登录按钮
    def page_click_login_btn(self):
        self.base_click(page.login_btn)

    # 获取提示框文本信息
    def page_get_err_info(self):
        return self.base_get_text(page.login_err)

    # 点击提示框确定按钮
    def page_click_err_btn_ok(self):
        self.base_click(page.login_err_btn_ok)

    # 截图
    def page_get_image(self):
        self.base_get_image()

    # 组装业务登录方法、给业务层调用
    def page_login(self,username,password,code):
        self.page_input_username(username)
        self.page_input_password(password)
        self.page_input_vertfy_code(code)
        self.page_click_login_btn()
# scripts 业务层

import unittest
from v4.page.page_login import PageLogin
from selenium import webdriver
from parameterized import parameterized

def get_data():
    return [("13822223333","123456","8888","账号不存在"),
            ("13822223333","1236","8888","密码错误")]


class Test_login(unittest.TestCase):
    login = None

    @classmethod
    def setUpClass(cls):
        cls.login = PageLogin()
        cls.login.page_click_login_lin()

    @classmethod
    def tearDownClass(cls):
        cls.login.driver.quit()


    def tearDown(self):
        self.login.driver.refresh()

    @parameterized.expand(get_data())
    def test_login(self,username,password,code,expect):
        self.login.page_login(username,password,code)
        msg = self.login.page_get_err_info()
        try:
            self.assertEqual(expect,msg)
            self.login.page_click_err_btn_ok()
        except AssertionError:
            self.login.page_get_image()
            # raise

单例模式:无论实例化多少对象 获取的同一个对象

用处:获取浏览器 都是一个

PO模式分层:面向对象思想 对象库层 操作层 业务层

就是进行三层代码的封装

列表也行 就是麻烦一点 list[0] list[1] 元组直接解包即可

dumps带s时转换 不带s是写json
dumps() 将字典转换成json字符串
json中dump()写入json
loads() 将字符串转为字典
load() 读取json方法
import json

# 将字典转换为json字符串

data = {"name":"小明","age":18}
print(type(data)) # <class 'dict'>

data = json.dumps(data)
print(type(data)) # <class 'str'>

print(data)
# {"name": "\u5c0f\u660e", "age": 18} 序列化

# 将字符串转为json
data = '{"name":"小明","age":18}' #属性:双引号
print(type(data)) # <class 'str'>

data = json.loads(data)
print(type(data)) # <class 'dict'>

print(data) # {'name': '小明', 'age': 18}  变成单引号了

JSON文件读写

ctrl+p 查看需要参数

加法测试项目V4PO加数据驱动

Base

base.py Base

from selenium import webdriver
from case_add import page


class GetDriver:
    # 设置类属性
    driver = None

    # 获取driver
    @classmethod
    def get_driver(cls):
        if cls.driver is None:
            # 实例化浏览器
            cls.driver = webdriver.Edge()
            # 最大化
            cls.driver.maximize_window()
            # 打开浏览器
            cls.driver.get(page.url)

        return cls.driver

    @classmethod
    def quit_driver(cls):
        if cls.driver:
            print("关闭之前:", cls.driver)
            cls.driver.quit()
            print("关闭之后:", cls.driver)

            cls.driver = None
            print("置空之后:", cls.driver)


if __name__ == '__main__':
    # 第一次获取浏览器
    print(GetDriver().get_driver())
    # 第二次获取浏览器
    print(GetDriver().get_driver())
    # 调用关闭,测试 关闭后driver是否为None
    GetDriver().quit_driver()
    print(GetDriver().get_driver())

虽然是同一个浏览器网址 但是将driver置空后

每次获取浏览器是一个全新的浏览器实例

为了确保在下次获取浏览器时可以重新实例化一个新的浏览器对象,而不是继续使用之前关闭的浏览器对象。

from selenium.webdriver.support.wait import WebDriverWait
import time


class Base:
    # 初始化方法
    def __init__(self, driver):
        self.driver = driver

    # 查找元素
    def base_find_element(self, loc, timeout=30, poll=0.5):
        """
        :param loc:  元素的定位信息,格式为元祖
        :param timeout: 默认超时时间30秒
        :param poll: 访问频率,默认0.5查找一次元素
        :return: 返回查找到的元素
        """
        # 显示等待
        return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))

    # 点击
    def base_click(self, loc):
        self.base_find_element(loc).click()

    # 获取value属性方法封装
    def base_get_element_text(self, loc):
        # 使用get_attribute()方法获取指定的元素属性值
        # 注意:返回
        return self.base_find_element(loc).get_attribute("value")

    # 截图
    def base_get_screen_shot(self):
        self.driver.get_screenshot_as_file("../../image/{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S")))

Page

init.py

from selenium.webdriver.common.by import By

"""以下为服务器域名配置地址"""
url = r"http://cal.apple886.com/"

"""以下为计算器配置数据"""
# number = By.CSS_SELECTOR,"#simple{}"

calc_add = By.CSS_SELECTOR,"#simpleAdd"
calc_equal = By.CSS_SELECTOR,"#simpleEqual"
calc_get_result = By.CSS_SELECTOR,"#resultIpt"
calc_clear = By.CSS_SELECTOR,"#simpleClearAllBtn"
num = "12345342"

for i in num:
    print("simple{}".format(i))
Page_calc.py 继承Base

PageCalc

from selenium.webdriver.common.by import By
from case_add.base.base import Base
from case_add import page


class PageCalc(Base):
    def page_num_click(self, num):
        for i in str(num):
            loc = By.CSS_SELECTOR, "#simple{}".format(i)
            self.base_click(loc)

    def page_add_btn(self):
        self.base_click(page.calc_add)

    def page_equal_btn(self):
        self.base_click(page.calc_equal)

    def page_get_result(self):
        return self.base_get_element_text(page.calc_get_result)

    def page_clear(self):
        self.base_click(page.calc_clear)

    def page_get_screen_shot(self):
        self.base_get_screen_shot()

    def page_calc(self, num1, num2):
        self.page_num_click(num1)
        self.page_add_btn()
        self.page_num_click(num2)
        self.page_equal_btn()

数据驱动

import json

def read_json(filename):
    filepath = "../data/"+ filename
    with open(filepath,"r",encoding="utf-8") as f:
        return json.load(f)

if __name__ == '__main__':
    data = read_json("calc.json")
    # print(data)
    # print("---" * 50)
    list1 = []
    for i in data.values():
        list1.append((i.get('a'),i.get('b'),i.get('expect')))

    print(list1)

业务层

import unittest
from case_add.tool.read_json import read_json
from case_add.base.get_driver import GetDriver
from case_add.page.page_calc import PageCalc
from parameterized import parameterized


def get_data():
    data = read_json("calc.json")
    arr = []
    for i in data.values():
        arr.append((i.get('a'), i.get('b'), i.get('expect')))

    return arr

class TestCal(unittest.TestCase):
    driver = None

    @classmethod
    def setUpClass(cls):
        cls.driver = GetDriver.get_driver()
        cls.calc = PageCalc(cls.driver)

    @classmethod
    def tearDownClass(cls):
        GetDriver.quit_driver()

    @parameterized.expand(get_data())
    def test_calc(self,num1,num2,expect):
        self.calc.page_calc(num1,num2)
        result = self.calc.page_get_result()
        try:
            self.assertEqual(str(expect),str(result))
            self.calc.page_clear()
        except AssertionError:
            self.calc.base_get_screen_shot()
            raise

正向和逆向用例是在软件测试中常用的概念。正向用例是使用软件时的预期行为,即用户按照设计好的流程和功能来操作软件系统,以测试系统是否按照预期的方式工作。而逆向用例则是用来测试系统对不符合预期情况的处理能力,即人为制造一些异常情况或错误操作,看系统如何响应。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/764386.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS2参数通信原理

执行ros2 service list 由于没有启动任何节点&#xff0c;因此查看服务器列表为空 执行ros2 run turtlesim turtlesim_node 启动服务节点 执行ros2 service list 将返回系统中当前活动的所有服务的列表: 执行 ros2 service call /turtlesim/list_parameters rcl_interfaces/…

证件照肤色不均匀怎么处理 证件照肤色调整最简单方式 证件照肤色很白符合要求吗 证件照制作软件免费下载

在我们的日常生活中&#xff0c;证件照扮演着至关重要的角色。它不仅是身份识别的关键&#xff0c;更是我们在各种正式场合展示自己形象的重要一环。那么今天我们就来聊聊关于证件照肤色不均匀怎么处理的问题及证件照肤色调整最简单方式。 一、证件照肤色不均匀怎么处理 对于…

面试官:你了解git cherry-pick吗

事情要从一次不规范的代码开发开始说起 背景故事 时间 2024年某个风平浪静的周五晚上 地点 中国&#xff0c;北京&#xff0c;西二旗&#xff0c;某互联网大厂会议室 人物 小杰&#xff0c;小A&#xff0c;小B&#xff0c;老K 对话 老K&#xff1a;昨天提交的代码被测试打回来…

数据结构——带环链表、循环队列问题

1.带环链表问题 1.1给定一个链表判断其是否带环 解决思路&#xff1a;利用快慢指针法&#xff0c;快指针一次走两步慢指针一次走一步&#xff0c;从链表起始位置遍历链表&#xff0c;如果链表带环&#xff0c;则快慢指针一定会在环中相遇&#xff0c;否则快指针先到达链表末尾…

OpenSSH Server 远程代码执行漏洞(CVE-2024-6387)(附代码)

OpenSSH Server 远程代码执行漏洞&#xff08;CVE-2024-6387&#xff09;&#xff08;附代码&#xff09; 前言影响范围验证脚本1.python2.C? 参考链接 前言 2024年7月1日&#xff0c;OpenSSH 官方发布安全通告&#xff0c;披露CVE-2024-6387 OpenSSH Server 远程代码执行漏洞…

【084】基于SpringBoot实现的家乡特色推荐系统

系统介绍 视频演示 点击查看演示视频 基于SpringBoot实现的家乡特色推荐系统主要采用SpringBootVue进行开发&#xff0c;系统整体分为管理员、用户两种角色&#xff0c;主要功能包括首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;文章分类管理&#xff0c;文章分…

鸿蒙开发Ability Kit(程序访问控制):【对所有应用开放】

对所有应用开放 在申请目标权限前&#xff0c;建议开发者先阅读[申请应用权限]&#xff0c;对权限的工作流程有基本了解后&#xff0c;再结合以下权限字段的具体说明&#xff0c;判断应用能否申请目标权限&#xff0c;提高开发效率。 说明&#xff1a; 权限级别为normal的权限…

Sharding-JDBC分库分表的基本使用

前言 传统的小型应用通常一个项目一个数据库&#xff0c;单表的数据量在百万以内&#xff0c;对于数据库的操作不会成为系统性能的瓶颈。但是对于互联网应用&#xff0c;单表的数据量动辄上千万、上亿&#xff0c;此时通过数据库优化、索引优化等手段&#xff0c;对数据库操作…

新手教学系列——【Python开发】不同系统更换pip源的方法

在使用Python进行开发时,你可能会发现使用pip安装包的速度较慢,尤其是在国内进行操作时。为了提高安装速度,我们可以将pip的默认源更换为国内的一些镜像源。本文将详细介绍如何在不同操作系统上进行这一操作,并给出常用的国内镜像源。 为什么要换源 pip默认使用的是官方的…

嵌入式Linux系统编程 — 6.2 signal和 sigaction信号处理函数

目录 1 信号如何处理 2 signal()函数 2.1 signal()函数介绍 2.2 示例程序 3 sigaction()函数 3.1 sigaction()函数介绍 3.2 示例程序 1 信号如何处理 信号通常是发送给对应的进程&#xff0c;当信号到达后&#xff0c; 该进程需要做出相应的处理措施&#xff0c;可以通…

IP地址与电商企业

网购作为我们现代生活不可或缺的部分&#xff0c;现如今电商企业蓬勃发展。 IP地址是网络世界中每一台设备的独特标识符&#xff0c;就像现实世界中每家每户的门牌号。对于电商企业而言&#xff0c;它在很多方面方面发挥着作用。 IP地址能够帮助电商企业精准地确定用户所在的地…

从理论到实践的指南:企业如何建立有效的EHS管理体系?

企业如何建立有效的EHS管理体系&#xff1f;对于任何企业&#xff0c;没有安全就谈不上稳定生产和经济效益&#xff0c;因此建立EHS管理体系是解决企业长期追求的建立安全管理长效机制的最有效手段。良好的体系运转&#xff0c;可以最大限度地减少事故发生。 这篇借着开头这个…

要不要从单片机转Linux?进来看看大神怎么说

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;究竟要不要从单片机转Linu…

对象的引用和常引用

前面曾介绍&#xff1a;一个变量的引用就是变量的别名。实际上&#xff0c;引用是一个指针常量&#xff0c;用来存放该变量的地址。如果形参为变量的引用&#xff0c;实参为变量名&#xff0c;则在调用函数进行虚实结合时&#xff0c;把实参变量的地址传给形参&#xff08;引用…

2024 年江西省研究生数学建模竞赛题目 B题投标中的竞争策略问题---完整文章分享(仅供学习)

问题&#xff1a; 招投标问题是企业运营过程中必须面对的基本问题之一。现有的招投标平台有国家级的&#xff0c;也有地方性的。在招投标过程中&#xff0c;企业需要全面了解招标公告中的相关信息&#xff0c;在遵守招投标各种规范和制度的基础上&#xff0c;选择有效的竞争策…

工业交换机端口统计功能

工业交换机端口统计功能不仅是一项技术手段&#xff0c;更是一双透视企业网络健康状态的慧眼。通过这一功能&#xff0c;企业能够实时捕捉到网络中每一个端口的流量情况&#xff0c;这不仅仅是数据的积累&#xff0c;更是对网络脉搏的精准把握。当网络的每一个脉动都被记录在案…

【每日一练】Python遍历循环

1. 情节描述&#xff1a;上公交车(10个座位)&#xff0c;并且有座位就可以坐下 要求&#xff1a;输入公交卡当前的余额&#xff0c;只要超过2元&#xff0c;就可以上公交车&#xff1b;如果车上有空座位&#xff0c;才可以上。 seat 10 while seat > 0:money int(input(…

springboot个人证书管理系统-计算机毕业设计源码16679

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了个人证书管理系统的开发全过程。通过分析个人证书管理系统管理的不足&#xff0c;创建了一个计算机管理个人证书管理系统的方案。文章介绍了个人证书管理系统的系…

计算机组成原理 | CPU子系统(4)MIPS32架构-单周期处理器设计

R型运算指令通路 I型运算指令通路 I型访存指令数据通路 I型分支 J型j指令 重新布局 继续整合通路&#xff1a;MUX多路选择器 控制方式 硬连接控制方式&#xff1a;依靠电路 微命令控制&#xff1a;将指令转换为微命令 控制信号的整理和编码 控制系统的两级控制方案 ALU控制器&…

大模型时代的基础架构,大模型算力中心建设指南重磅来袭!

什么是最畅销商品&#xff1f;什么是高毛利商品&#xff1f; 我们来看一个例子&#xff1a; 一件T恤使用成本为100元的原料&#xff0c;价格为140元。另一件T恤使用成本为80元的原料&#xff0c;但在样式、颜色、图案的设计上比较有特色&#xff0c;价格也为140元。 当这两件…
最新文章