自动化测试-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 sleepclass 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 WebDriverWaitclass 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 PageLoginclass 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 jsondef read_json(filename,key):filepath = os.path.dirname(os.path.dirname(__file__)) + os.sep + "data" + os.sep + filenamearr = []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_jsonclass 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)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode经典困难题-接雨水

. - 力扣(LeetCode) 42. 接雨水 困难 相关标签 相关企业 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,…

c++的学习之路:22、多态(1)

摘要 本章主要是说一些多态的开头。 目录 摘要 一、多态的概念 二、多态的定义及实现 2.1、多态的构成条件 2.2、虚函数 2.3、虚函数的重写 2.4、C11 override 和 final 2.5、重载、覆盖(重写)、隐藏(重定义)的对比 三、思维导图 一、多态的概念 多态的概念&#…

HCIP实验:MGRE、星型拓扑

一、实验要求 1,R6为ISP只能配置IP地址,R1-R5的环回为私有网段 2,R1/4/5为全连的MGRE结构,R1/2/3为星型的拓扑结构,R1为中心站点 3,所有私有网段可以互相通讯,私有网段使用OSPF完成。 二、实验…

数字乡村创新实践探索农业现代化与农村治理现代化新路径:科技赋能农村全面振兴与农民幸福生活

目录 引言 一、数字乡村与农业现代化 1、智慧农业技术的应用 2、农业产业链的数字化转型 二、数字乡村与农村治理现代化 1、农村信息化水平的提升 2、农村治理模式的创新 三、科技赋能农村全面振兴与农民幸福生活 1、提升农业生产效益与农民收入 2、促进农村产业结构…

SpringCloud系列(2)--SpringCloud和SpringBoot技术选型

前言:SpringCloud是微服务架构的一揽子解决方案,SpringBoot是一种技术,要使用SpringCloud,也需要使用到SpringBoot,所以要使用SpringCloud时,必须也要考虑到SpringBoot的适配问题 1、查看SpringCloud和与之…

学生管理系统控制台版(java)

首先得先写个Student类,用来存放学生信息 public class Student {private String id;private String name;private int age;private String address;public Student() {}public Student(String id, String name, int age, String address) {this.id id;this.name…

C++面向对象程序设计-北京大学-郭炜【课程笔记(六)】

C面向对象程序设计-北京大学-郭炜【课程笔记&#xff08;六&#xff09;】 1、可变长数组类的实现2、流插入运算符和流提取运算符的重载2.1、对形如cout << 5 ; 单个"<<"进行重载2.2、对形如cout << 5 << “this” ;连续多个"<<&…

蓝桥杯-最大子矩阵

问题描述 下面是一个 20x20 的矩阵&#xff0c;矩阵中的每个数字是一个1到9之间的数字&#xff0c;请注意显示时去除了分隔符号。 6985924183938786894117615876963131759284373473483266274834855367125655616786474316121686927432329479135474133499627734472797994592984…

⑤-1 学习PID--什么是PID

​ PID 算法可以用于温度控制、水位控制、飞行姿态控制等领域。后面我们通过PID 控制电机进行说明。 自动控制系统 在直流有刷电机的基础驱动中&#xff0c;如果电机负载不变&#xff0c;我们只要设置固定的占空比&#xff08;电压&#xff09;&#xff0c;电机的速度就会稳定在…

ceph rbd部署与使用

一、前言 Ceph RBD&#xff08;Rados Block Device&#xff09;是 Ceph 存储解决方案的一部分&#xff0c;它提供了一个分布式块设备服务&#xff0c;允许用户创建和管理虚拟块设备&#xff0c;类似于传统的本地磁盘&#xff0c;Ceph RBD 是一个高度可扩展的存储解决方案&#…

C语言:关于动态内存管理我到底应该懂些什么?看了我这篇你就通透了。

1.动态内存的分配 在我们初学C语言的时候&#xff0c;我们经常用一下几种方式申请内存空间。 int a 10;//在栈空间上开辟4个字节存放这个值。 char arr[10] {1,2,3,4,5,6,7,8,9,10};//在栈空间上开辟10个字节的连续空间。但是上述开辟空间有两个特点 1.空间开辟大小是固定的…

FJSP:袋鼠群优化(Kangaroo Swarm Optimization ,KSO)算法求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…

微服务之Consul 注册中心介绍以及搭建

一、微服务概述 1.1单体架构 单体架构&#xff08;monolithic structure&#xff09;&#xff1a;顾名思义&#xff0c;整个项目中所有功能模块都在一个工程中开发&#xff1b;项目部署时需要对所有模块一起编译、打包&#xff1b;项目的架构设计、开发模式都非常简单。 当项…

C++ | Leetcode C++题解之第22题括号生成

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<string> res; //记录答案 vector<string> generateParenthesis(int n) {dfs(n , 0 , 0, "");return res;}void dfs(int n ,int lc, int rc ,string str){if( lc n && rc n…

美团笔试复盘

昨天做了美团的笔试&#xff0c;现在复盘一下。 1、将数组按照绝对值大小排序 有道算法题解决思路需要将数组按照绝对值大小进行排序&#xff0c;我使用的是sort方法Comparator比较器实现的&#xff0c;这里记录一下&#xff1a; public static void main(String[] args) {In…

第二证券策略:股指预计维持震荡格局 关注汽车、工程机械等板块

第二证券指出&#xff0c;指数自今年2月份阶段低点反弹以来&#xff0c;3月份持续高位整理。进入4月份之后面对年报和一季报的双重财报发表期&#xff0c;预计指数短期保持高位整理概率比较大。前期缺乏成绩支撑的概念股或有回落的危险&#xff0c;主张重视成绩稳定、估值低、分…

【Leetcode】1702. 修改后的最大二进制字符串

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个二进制字符串 b i n a r y binary binary &#xff0c;它仅有 0 0 0 或者 1 1 1 组成。你可以使用下面的操作任意次对它进行修改&#xff1a; 操作 1 &#xff1a;如果…

Golang(一):基础、数组、map、struct

目录 hello world 变量 常量&#xff0c;iota 函数 init函数和导包过程 指针 defer 数组和动态数组 固定长度数组 遍历数组 动态数组 len 和 cap 截取 切片的追加 map 四种声明方式 遍历map 删除 查看键是否存在 结构体 声明 作为形参 方法 封装 继承…

[入门到放弃]设计模式-笔记

模块化设计 20240448 模块不包含数据&#xff0c;通过实例的指针&#xff0c;实现对实例的操作&#xff1b;唯一包含的数据是用于管理这些模块的侵入式链表模块只负责更具定义的数据结构&#xff0c;执行对应的逻辑&#xff0c;实现不同实例的功能&#xff1b; 参考资料 使用…

【热门话题】常见分类算法解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 常见分类算法解析1. 逻辑回归&#xff08;Logistic Regression&#xff09;2. 朴…