selenium高级自动化编程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:学完本篇文章,自动化测试算是入门了


提示:以下是本篇文章正文内容,下面案例可供参考

一、环境准备

1、python3.7
2、pycharm
3、selenium
4、xpath与chrome控件

selenium下载
cmd窗口下输入:pip install selenium
版本问题可能导致安装失败

xpath控件在Google应用商店下载
在这里插入图片描述

chrome控件放入python安装的根目录
在这里插入图片描述
下载地址:http://chromedriver.storage.googleapis.com/index.html
请与chrome浏览器的版本相对应,否则无法启动

二、webdriver

操作浏览器的基本方法

在这里插入图片描述

元素定位

在这里插入图片描述
在这里插入图片描述

xpath定位

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
xpath模糊匹配
在这里插入图片描述
在这里插入图片描述

css定位

在这里插入图片描述

操作元素(键盘和鼠标事件)

简单操作

1.点击(鼠标左键)页面按钮:click()
2.请空输入框:clear()
3.输入字符串:send_keys()
4.截屏保存
driver.get_screenshot_as_file(u"C:\Users\Administrator\Desktop\123456\%s.png" % datetime.now().strftime("%Y%m%d.%H%M%S.%f")[:-3])
在这里插入图片描述

submit 提交表单

1.在前面百度搜索案例中,输入关键字后,可以直接按回车键搜索,也可以点搜索按钮
搜索。
2.submit()一般用于模拟回车键
在这里插入图片描述

键盘操作

1.selenium 提供了一整套的模拟键盘操作事件,前面 submit()方法如果不行的话,可以试试模拟键盘事件
2.模拟键盘的操作需要先导入键盘模块:from selenium.webdriver.common.keys import Keys
3.模拟 enter 键,可以用 send_keys(Keys.ENTER)
在这里插入图片描述
4.其它常见的键盘操作:
键盘 F1 到 F12:send_keys(Keys.F1) 把 F1 改成对应的快捷键
复制 Ctrl+C:send_keys(Keys.CONTROL,‘c’)
粘贴 Ctrl+V:send_keys(Keys.CONTROL,‘v’)
全选 Ctrl+A:send_keys(Keys.CONTROL,‘a’)
剪切 Ctrl+X:send_keys(Keys.CONTROL,‘x’)
制表键 Tab: send_keys(Keys.TAB)

鼠标悬停事件

1.鼠标不仅仅可以点击(click),鼠标还有其它的操作,如:鼠标悬停在某个元素上,鼠标右击,鼠标按住某个按钮拖动
2.鼠标事件需要先导入模块:from selenium.webdriver.common.action_chains import ActionChains
perform() 执行所有 ActionChains 中的行为
move_to_element() 鼠标悬停
在这里插入图片描述
在这里插入图片描述
右击鼠标:context_click()
双击鼠标:double_click()

多窗口、句柄(handle)

有些页面的链接打开后,会重新打开一个窗口,对于这种情况,想在新页面上操作,就得先切换窗口了。获取窗口的唯一标识用句柄表示,所以只需要切换句柄,我们就能在多个页面上灵活自如的操作了。
本篇以打开百度新闻页面搜索按钮上的链接页面为例,依次打开每个按钮,并检验测试结果。用脚本批量操作,可以减少重复劳动,重复的事情让脚本去执行吧!

获取窗口句柄

1.打开百度新闻页面:17http://news.baidu.com/17
3.当点击百度新闻页面上新闻时,会打开一个新的窗口
3.人为操作的话,可以通过点击窗口切换到不同的窗口上,但是脚本它不
知道你要操作哪个窗口,这时候只能获取窗口唯一的标识:句柄
4.获取当前页面的句柄:driver.current_window_handle
5.获取所有窗口的句柄:driver.window_handles
在这里插入图片描述

句柄切换

在这里插入图片描述

iframe

有很多小伙伴在拿 163 作为登录案例的时候,发现不管怎么定位都无法定位到,到底是什么鬼呢,下面详细介绍 iframe 相关的切换

frame 和 iframe 区别

frame 与 iframe 两者可以实现的功能基本相同,不过 iframe 比 frame 具有更多的灵活性。 frame 是整个页面的框架,iframe 是内嵌的网页元素,也可以说是内嵌的框架

iframe 标记又叫浮动帧标记,可以用它将一个 HTML 文档嵌入在一个 HTML中显示。它和 Frame 标记的最大区别是在网页中嵌入 的所包含的内容与整个页面是一个整体,而< /frame>所包含的内容是一个独立的个体,是可以独立显示的。另外,应用 iframe 还可以在同一个页面中多次显示同一内容,而不必重复这段内容的代码。

163 登录界面

确认登陆在iframe框架下
在这里插入图片描述

切换iframe

iframe 的切换是默认支持 id 和 name 的方法的
在这里插入图片描述

select 下拉框

认识 select

1.打开百度-设置-高级搜索设置界面,如下图所示
在这里插入图片描述

二次定位

界面改版,提供老版本百度下拉框定位方式,主要是为了了解流程,现版本不可用

选项有三个

每页显示 10 条 每页显示 20 条 每页显示 50 条

在这里插入图片描述

直接定位

可直接用
在这里插入图片描述

其他定位方式

这里只提供方法
在这里插入图片描述

弹窗操作

不是所有的弹出框都叫 alert,在使用 alert 方法前,先要识别出到底是不是alert。先认清楚 alert 长什么样子,下次碰到了,就可以用对应方法解决。
alert\confirm\prompt 弹出框操作主要方法有:
text:获取文本值
accept() :点击"确认"
dismiss() :点击"取消"或者叉掉对话框
send_keys() :输入文本值 --仅限prompt,在 alert 和 confirm 上没有输入框

alert\confirm\prompt

html代码如下,复制下面代码,改为html后缀的文件
在这里插入图片描述

<html>
<head>
<title>Alert</title>
</head>
<body>
<input id = "alert" value = "alert" type = "button" onclick = "alert('您关注了 ht 吗?');"/>
<input id = "confirm" value = "confirm" type = "button" onclick ="confirm('确定关注微信公众号:ht?');"/>
<input id = "prompt" value = "prompt" type = "button" onclick = "var name= prompt('请输入微信公众号:','ht'); document.write(name)"/>
</body>
</html> 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

alert 操作
1.先用 switch_to.alert()方法切换到 alert 弹出框上
2.可以用 text 方法获取弹出的文本 信息
3.accept()点击确认按钮
4.dismiss()相当于点右上角 x,取消弹出框
(url 的路径,直接复制浏览器打开的路径)
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\122.html"
driver.get(url)
sleep(2)
driver.find_element_by_id("alert").click()  #点击”alert按钮“
sleep(2)
t = driver.switch_to.alert  #切换到alert弹出框
print(t.text)
t.accept()  #点击弹出框确认按钮
driver.find_element_by_id("alert").click()
sleep(2)
t = driver.switch_to.alert
t.dismiss()  #退出弹出框
confirm 操作
1.先用 switch_to_alert()方法切换到 alert 弹出框上
2.可以用 text 方法获取弹出的文本 信息
3.accept()点击确认按钮
4.dismiss()相当于点取消按钮或点右上角 x,取消弹出框
(url 的路径,直接复制浏览器打开的路径)
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\122.html"
driver.get(url)
sleep(2)
driver.find_element_by_id("confirm").click()  #点击”confirm"按钮
sleep(2)
t = driver.switch_to.alert  #切换到alert弹出框
print(t.text)
t.accept()  #点击弹出框确认按钮
driver.find_element_by_id("alert").click()
sleep(2)
t = driver.switch_to.alert
t.dismiss()  #退出弹出框,相当于取消按钮
prompt 操作
1.先用 switch_to_alert()方法切换到 alert 弹出框上
2.可以用 text 方法获取弹出的文本 信息
3.accept()点击确认按钮
4.dismiss()相当于点右上角 x,取消弹出框
5.send_keys()这里多个输入框,可以用 send_keys()方法输入文本内容
(url 的路径,直接复制浏览器打开的路径)
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\122.html"
driver.get(url)
sleep(2)
driver.find_element_by_id("prompt").click()  #点击”confirm"按钮
sleep(2)
t = driver.switch_to.alert  #切换到alert弹出框
print(t.text)
t.send_keys("hello word")   #输入文本信息
sleep(2)
t.accept()  #点击弹出框确认按钮
#t.dismiss()  #退出弹出框,相当于取消按钮

单选框和复选框

HTML源码

<html>
<head>
<meta http-equiv="content-type"
content="text/html;charset=utf-8" />
<title>单选和复选</title>
</head>
<body>
</form>
<h4>单选:性别</h4>
<form>
<label value="radio"></label>
<input name="sex" value="male" id="boy" type="radio"><br>
<label value="radio1"></label>
<input name="sex" value="female" id="girl" type="radio">
</form>
<h4>微信公众号:selenium高级自动化编程</h4>
<form>
<!-- <label for="c1">checkbox1</label> -->
<input id="c1" type="checkbox">selenium<br>
<!-- <label for="c2">checkbox2</label> -->
<input id="c2" type="checkbox">python<br>
<!-- <label for="c3">checkbox3</label> -->
<input id="c3" type="checkbox">appium<br>
<!-- <form>
<input type="radio" name="sex" value="male" /> Male
<br />
<input type="radio" name="sex" value="female" /> Female
</form> -->
</body>
</html>

在这里插入图片描述

单选框
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\233.html"
driver.get(url)
a = driver.find_element_by_id("boy").is_selected()    #判断是否被选择
b = driver.find_element_by_id("girl").is_selected()
print("boy是否选中:",a)
print("girl是否选中:",b)
driver.find_element_by_id("boy").click()   #点击单选
a1 = driver.find_element_by_id("boy").is_selected()
b1 = driver.find_element_by_id("girl").is_selected()
print("boy是否选中:",a1)
print("girl是否选中:",b1)
sleep(2)
driver.find_element_by_id("girl").click()  #点击单选
复选框:checkbox
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\233.html"
driver.get(url)
a = driver.find_element_by_id("c1").is_selected()    #判断是否被选择
b = driver.find_element_by_id("c2").is_selected()
print("selenium是否选中:",a)
print("python是否选中:",b)
driver.find_element_by_id("c1").click()   #点击单选
sleep(2)
a1 = driver.find_element_by_id("c1").is_selected()
b1 = driver.find_element_by_id("c2").is_selected()
print("selenium是否选中:",a1)
print("python是否选中:",b1)
driver.find_element_by_id("c1").click()   #点击单选
driver.find_element_by_id("c2").click()   #点击单选
driver.find_element_by_id("c3").click()   #点击单选
sleep(2)
a11 = driver.find_element_by_id("c1").is_selected()
b11 = driver.find_element_by_id("c2").is_selected()
print("selenium是否选中:",a11)
print("python是否选中:",b11)
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\233.html"
driver.get(url)
#find_elements_by_xpath与find_element_by_xpath
checkbox = driver.find_elements_by_xpath("//*[@type='checkbox']")
#全部勾选
for i in checkbox:
    i.click()

table 定位

源码

<!DOCTYPE html>
<meta charset="UTF-8"> <!-- for HTML5 -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<html>
	<head>
		<title>Table 测试模板</title>
	</head>
	<body>
		<table border="1" id="myTable">
			<tr>
				<th>QQ 群</th>
				<th>QQ 号</th>
				<th>群主</th>
			</tr>
			<tr>
				<td>selenium高级自动化编程</td> 
				<td>123456</td>
				<td>ht</td>
			</tr>
			<tr>
				<td>appium 自动化</td>
				<td>123456789</td>
				<td>ht</td>
			</tr>
		</table>
	</body>
</html>

在这里插入图片描述
table特征:

1.table 页面查看源码一般有这几个明显的标签:table、tr、th、td
2.<table>标示一个表格
3.<tr>标示这个表格中间的一个行
4.</th> 定义表头单元格
5.</td> 定义单元格标签,一组<td>标签将建立一个单元格,<td>标签必须放在<tr>标签内
xpath 定位 table
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
url = "C:\\Users\\Administrator\\Desktop\\222.html"
driver.get(url)
#定位selenium高级自动化编程  /tbody/必须加
t = driver.find_element_by_xpath("//table[@id='myTable']/tbody/tr[2]/td[1]")
print(t.text)
富文本练习

最后写入图片的时候错误,暂时没找到原因

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
from selenium.webdriver.common.keys import Keys

url = "https://www.cnblogs.com/"
driver.get(url)
driver.maximize_window()
sleep(2)

#登陆
driver.find_element_by_xpath("//*[@id='navbar_login_status']/a[4]").click()
driver.find_element_by_id("mat-input-0").send_keys("192@qq.com")
driver.find_element_by_id("mat-input-1").send_keys("ht5")
driver.find_element_by_id("mat-input-1").send_keys(Keys.ENTER)
sleep(10)

#进入文本编辑器
#//*[@id="myblog_icon"]
driver.find_element_by_xpath("//*[@id='myblog_icon']").click()
sleep(3)
driver.find_element_by_xpath("//*[@id='blog_nav_newpost']").click()
sleep(2)

#标题输入
driver.find_element_by_id("post-title").send_keys("测试")
sleep(2)

#正文输入
driver.switch_to.frame("Editor_Edit_EditorBody_ifr")
driver.find_element_by_id("tinymce").send_keys("测试成功")
driver.switch_to.default_content()
sleep(2)
#图片上传
driver.find_element_by_id("Editor_Edit_EditorBody_uploadImage").click()
sleep(4)
#<iframe id="mce_80_ifr" frameborder="0" >iframe为动态
iframe = driver.find_elements_by_tag_name("iframe")  #获取所有的frame
iframe = driver.find_elements_by_tag_name("iframe")[1]
driver.switch_to_frame(iframe)
driver.find_element_by_name('file').send_keys(r"C:\\Users\\Administrator\\Desktop\\home\\pill\\img\\bg1.png")

print(len(iframe))


# driver.switch_to.frame(iframe)
# sleep(2)
#driver.find_element_by_xpath("//*[@id='jquery-wrapped-fine-uploader']/div/div/input").send_keys(r"C:\\Users\\Administrator\\Desktop\\home\\pill\\img\\bg1.png")
#driver.find_element_by_name("file").send_keys(r"C:\\Users\\Administrator\\Desktop\\home\\pill\\img\\bg1.png")
#driver.find_element_by_xpath("//*[@id='jquery-wrapped-fine-uploader']/div/div/input").click()
#driver.find_element_by_name('file').click()

获取页面元素

通常在做断言之前,都要先获取界面上元素的属性,然后与期望结果对比

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
sleep(2)
#获取页面标题
title = driver.title
print("网页标题:",title)
#获取元素的文本
text = driver.find_element_by_xpath("//*[@id='bottom_layer']/div[1]/p[1]/a").text
print("元素文本:",text)
#获取元素的标签
tag = driver.find_element_by_id("kw").tag_name
print("百度输入框元素标签:",tag)
#获取其它属性方法:get_attribute("属性"),这里的参数可以是 class、name 等任意属性
classname = driver.find_element_by_id("kw").get_attribute("class")
print("百度输入框的class属性:",classname)
#获取输入框内的文本值
driver.find_element_by_id("kw").send_keys("input的文本值")
value = driver.find_element_by_id("kw").get_attribute("value")
print("已经输入的文本值:",value)
#获取浏览器名称
browser = driver.name
print("浏览器标识符:",browser)

在这里插入图片描述

爬取网页源码

有时候通过元素的属性的查找页面上的某个元素,可能不太好找,这时候可以从源码中爬出想要的信息。selenium 的page_source 方法可以获取到页面源码。

page_source

selenium的page_source可以直接返回网页源码

#coding:utf-8
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
page = driver.page_source
print(page)
re 非贪婪模式
#coding:utf-8
from selenium import webdriver
import re   #正则表达式,非贪婪模式启动
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/weixin_44487337")
page = driver.page_source
#findall返回的是一个列表,同时过滤非href  不同的去学习一下正则表达式
url_list = re.findall('href=\"(.*?)\"',page,re.S)
url_all = []  #定义一个空的列表
for url in url_list:
    if "http" in url:
        print(url)
        url_all.append(url)  #列表写入
print(url_all)

cookie相关

虽然 cookie 相关操作在平常 ui 自动化中用得少,偶尔也会用到,比如登录有图形验证码,可以通过绕过验证码方式,添加 cookie 方法登录。
登录后换账号登录时候,也可作为后置条件去删除 cookie 然后下个账号登录

获取 cookies:get_cookies()

1.获取 cookies 方法直接用:get_cookies()
2.先启动浏览器,获取 cookies,打印出来发现是空:[]
3.打开博客首页后,重新获取 cookies,打印出来,就有值了

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
from selenium.webdriver.common.keys import Keys
cokkie_3 =driver.get_cookies()
print(cokkie_3)
url = "https://www.cnblogs.com/"
driver.get(url)
driver.maximize_window()
sleep(2)
cokkie_1 =driver.get_cookies()
print(cokkie_1)

在这里插入图片描述

登录后的 cookies
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
from selenium.webdriver.common.keys import Keys
cokkie_3 =driver.get_cookies()
print(cokkie_3)
url = "https://www.cnblogs.com/"
driver.get(url)
driver.maximize_window()
sleep(2)
cokkie_1 =driver.get_cookies()
print(cokkie_1)

#登陆
driver.find_element_by_xpath("//*[@id='navbar_login_status']/a[4]").click()
driver.find_element_by_id("mat-input-0").send_keys("******")
driver.find_element_by_id("mat-input-1").send_keys("******")
driver.find_element_by_id("mat-input-1").send_keys(Keys.ENTER)
sleep(10)
cokkie_2 =driver.get_cookies()
print(cokkie_2)

如下图,name与value发生变化
name与value发送变化

获取登陆的cookie

1.get_cookies(): 获 取 所 有 cookies 2.driver.get_cookie(name):获取指定 name 的 cookie:
3. 清 除 指 定 cookie:delete_cookie() 4.delete_all_cookies():清除所有 cookies
5.add_cookie(cookie_dict):添加 cookie 的值

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
from selenium.webdriver.common.keys import Keys
url = "https://www.cnblogs.com/"
driver.get(url)
driver.maximize_window()
sleep(2)
#登陆
driver.find_element_by_xpath("//*[@id='navbar_login_status']/a[4]").click()
driver.find_element_by_id("mat-input-0").send_keys("*****")
driver.find_element_by_id("mat-input-1").send_keys("*****")
driver.find_element_by_id("mat-input-1").send_keys(Keys.ENTER)
sleep(10)
cookie_1 = driver.get_cookie(name=".Cnblogs.AspNetCore.Cookies") #获取登陆的cookie
print(cookie_1)
cookie_2 = driver.get_cookies()  #获取所有的cookie
print(cookie_2)
driver.delete_cookie(name=".Cnblogs.AspNetCore.Cookies")  #删除登陆的cookie
# driver.delete_all_cookies() #清除所有的cookie
sleep(8)
driver.refresh()  #刷新界面,用户已经退出,证明.Cnblogs.AspNetCore.Cookies是登陆的cookie的一部分
使用cookie绕过验证码登陆

.get_cookies()获取到的cookie与浏览器F12获取的如下图,一模一样
在这里插入图片描述

在这里插入图片描述

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
from selenium.webdriver.common.keys import Keys
url = "https://www.cnblogs.com/"
driver.get(url)
driver.maximize_window()
sleep(2)
#添加cookie
u1 = {"domain":"cnblogs.com",
      "name":"CNBlogsCookie",
      "value":"23D8B5601F6AB78B3E87252F6B9CE00C0956B74C85DF818407C639E5410A57BD25B79BEDE403F8EC22EF61CA4F0CA5C419A93AABF4F7C1036F20E36C9B2524591E53C2671CC18B2FFC5556B8BFEEF0D264C0EB43"}
u2 = {"domain":"cnblogs.com",
      "name":".Cnblogs.AspNetCore.Cookies",
      "value":"CfDJ8AHUmC2ZwXVKl7whpe9_lavnfct879j1VAOlH63-UUvF8AmiipR8olNqV5q_DUtgfSwtV8RbB38VyJkoYckyrIpLrjEp-YXrwt63w9LhT5Mx-后面太长我就不粘贴了"}
driver.add_cookie(u1)
driver.add_cookie(u2)
sleep(5)
driver.refresh() #这里刷新后发现用户已登录,亲测有效

三、使用JavaScript

有些特殊的操作 selenium2+python 无法直接完成的,JS 刚好是这方面的强项
链接: http://www.w3school.com.cn/js/index.asp4

控制滚动条

通过标尺拖动滚动条

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.bilibili.com/")
driver.set_window_size(500,800)
sleep(3)
driver.execute_script("window.scrollTo(200,400)")

通过元素拖动滚动条

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.52pojie.cn/")
target = driver.find_element_by_xpath("//*[@id='ct']/div[3]/div[3]/div[3]/div[1]/h2/a")
driver.execute_script("arguments[0].scrollIntoView();", target)

日历控件readonly

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.12306.cn/")
sleep(2)
"""
<input type="text" class="input inp-txt_select" value="2018-07-21" id="train_date" readonly>
"""
#去掉元素readonly属性
js = 'document.getElementById("train_date").removeAttribute("readonly");'
driver.execute_script(js)
sleep(3)
#用JS方法输入日期
js_value= 'document.getElementById("train_date").value="2020-12-07"'
driver.execute_script(js_value)
#清空后重新输入
sleep(3)
driver.find_element_by_id("train_date").clear()
driver.find_element_by_id("train_date").send_keys("2020-12-09")

内嵌滚动条

页面源码

<!DOCTYPE html> 
<meta charset="UTF-8"> <!-- for HTML5 --> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<html> 
	<head> 
		<style type="text/css">		
			div.scroll 
			{
				background-color:#afafaf; width:500px;  height:100px; overflow:auto; 
			} 
 
 
		</style> 
	</head> 
	<body> 
		<p>测试滚动条</p> 
		<p>这是一个内嵌的div滚动条</p> 
		<div id="kw" name="kww" class="scroll">
		这是一个内嵌 div:物联网平台支持为产品定义物模型,将实际产品抽象成由属性、服务、事件所组成的数据模型,便于云端管理和数据交互。产品创建完成后,您可以为它定义物模型,产品下的设备将自动继承物模型内容。草稿发布之后会变为正式版本,发布一次就新增一次版本!!功能定义又分为两个页签,标准功能和自定义功能。
		下面列出了设备厂商接入时的常见问题,强烈建议设备厂商将这些问题浏览一遍以加深对阿里云IoT物联网。平台以及Link SDK的了解。 使用具体编程语言SDK时碰到的问题,请参考相应语言zhegedancihenchanghenchangchangchangchangchanchanchanchangchangchangchancg
		</div> 
	</body> 
</html> 

拖动操作

#encoding:utf-8
from selenium import webdriver
from time import sleep
driver=webdriver.Chrome()
driver.get('file:///C://Users//Administrator//Desktop//hh.html')
sleep(2)

# 竖向滚动条操作
js1='var q=document.getElementById("kw").scrollTop = 10000'
driver.execute_script(js1)
sleep(2)
js2='var q=document.getElementById("kw").scrollTop = 0'
driver.execute_script(js2)
sleep(2)

# 横向滚动条操作
js3='var q=document.getElementById("kw").scrollLeft = 10000'
driver.execute_script(js3)
sleep(2)
js4='var q=document.getElementById("kw").scrollLeft = 0'
driver.execute_script(js4)
sleep(2)

# 用classname
js5 = "var q=document.getElementsByClassName('scroll')[0].scrollTop = 10000"
driver.execute_script(js5)
sleep(2)
js6 = "var q=document.getElementsByClassName('scroll')[0].scrollLeft = 10000"
driver.execute_script(js6)

元素属性修改

JS处理多窗口,在自动化过程中多窗口情况处理往往很麻烦,可以通过修改target属性来防止多窗口情况发生
在这里插入图片描述

from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
sleep(3)
#登陆
driver.find_element_by_xpath("//*[@id='u1']/a").click()
sleep(5)
driver.find_element_by_xpath("//*[@id='TANGRAM__PSP_11__footerULoginBtn']").click()
sleep(2)
driver.find_element_by_id("TANGRAM__PSP_11__userName").send_keys("******")
sleep(1)
driver.find_element_by_id("TANGRAM__PSP_11__password").send_keys("******")
sleep(1)
driver.find_element_by_id("TANGRAM__PSP_11__submit").click()
sleep(5)
#删除元素属性
js='document.getElementById("s-top-username").removeAttribute("target")'
driver.execute_script(js)
#这里不会创建新的窗口
driver.find_element_by_xpath("//*[@id='s-top-username']/span[2]").click()
#给id为s-top-username的元素 增加 title属性并赋值为“测试title”
js='document.getElementById("s-top-username").setAttribute("title","测试title")'
#给id为s-top-username的元素 删除 title属性
js='document.getElementById("s-top-username").removeAttribute("title")'
#获取id为s-top-username的元素 title属性的值
js='document.getElementById("s-top-username").getAttribute("title")'
#修改id为s-top-username的元素 title属性的值
js='document.getELementById("s-top-username").title="测试"'
注意:
getELementBy***
例:
getELementByClassName
getELementByName

四、浏览器打开python帮助文档

打开cmd窗口,输入python -m pydoc -p 10000
在这里插入图片描述
浏览器输入网址:http://localhost:10000/
在这里插入图片描述

五、Unittest

python 的单元测试框架,是基于 java 的 junit 测试框架。

案列1

# encoding = utf-8
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
import unittest
class Blog(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.cnblogs.com/htxz/")
        #测试用例的名称要以 test 开头 
    def test_blog(self):
        sleep(3)
        #判断当前页面的title是否完全等于预期字符串,返回布尔值
        result = EC.title_is("会走路的桃子 - 博客园")(self.driver)
        # 打印出True还是 False
        print(result)
        #测试该表达式是真值
        self.assertTrue(result)
    def tearDown(self):
        self.driver.quit()
if __name__ == "__main__":
    unittest.main()

expected_condtions

16种判断页面元素的方法

from selenium.webdriver.support import expected_conditions
expected_condtions提供了16种判断页面元素的方法:

1.title_is:判断当前页面的title是否完全等于预期字符串,返回布尔值

2.title_contains:判断当前页面的title是否包含预期字符串,返回布尔值

3.presence_of_element_located:判断某个元素是否被加到dom树下,不代表该元素一定可见

4.visibility_of_element_located:判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不为0

5.visibility_of:跟上面的方法是一样的,只是上面需要传入locator,这个方法直接传定位到的element就好

6.presence_of_all_elements_located:判断是否至少一个元素存在于dom树中,举个例子,如果页面上有n个元素的class都是'coumn-md-3',name只要有一个元素存在,这个方法就返回True

7.text_to_be_present_in_element:判断某个元素中的text文本是否包含预期字符串

8.text_to_be_present_in_element_value:判断某个元素中的value属性值是否包含了预期字符串

9.frame_to_be_availabe_and_switch_to_it:判断该frame是否可以switch进去,如果可以,则返回True并且switch进去,否则返回False

10.invisibility_of_element_located:判断某个元素是否不存在于dom树或不可见

11.element_to_be_clickable:判断某个元素是见并且是enable(有效),这样的话才叫clickable

12.staleness_of:等某个元素从dom树下移除,返回TrueFalse

13.element_to_be_selected:判断某个元素是否被选中,一般用于select下拉表

14.element_selection_state_to_be:判断某个元素的选中状态是否符合预期

15.element_located_selection_state_to_be:跟上面的方法一样,只是上面的方法传入定位到的element,这个方法传入locator

16.alert_is_present:判断页面上是会否存在alert

断言方法

方法描述
assertEqual(arg1, arg2, msg=None)验证arg1=arg2,不等则fail
assertNotEqual(arg1, arg2, msg=None)验证arg1 != arg2, 相等则fail
assertTrue(expr, msg=None)验证expr是true,如果为false,则fail
assertFalse(expr,msg=None)验证expr是false,如果为true,则fail
assertIs(arg1, arg2, msg=None)验证arg1、arg2是同一个对象,不是则fail
assertIsNot(arg1, arg2, msg=None)验证arg1、arg2不是同一个对象,是则fail
assertIsNone(expr, msg=None)验证expr是None,不是则fail
assertIsNotNone(expr, msg=None)验证expr不是None,是则fail
assertIn(arg1, arg2, msg=None)验证arg1是arg2的子串,不是则fail
assertNotIn(arg1, arg2, msg=None)验证arg1不是arg2的子串,是则fail
assertIsInstance(obj, cls, msg=None)验证obj是cls的实例,不是则fail
assertNotIsInstance(obj, cls, msg=None)验证obj不是cls的实例,是则fail

案例2

from selenium import webdriver
from time import sleep
#导入键盘操作模块
from selenium.webdriver.common.keys import Keys
import unittest
class Blog(unittest.TestCase):
    #登陆网站
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.cnblogs.com/")
    #参数化登陆账号密码
    def login(self,username,psw):
        self.driver.find_element_by_xpath("//*[@id='navbar_login_status']/a[4]").click()
        self.driver.find_element_by_id("mat-input-0").send_keys(username)
        self.driver.find_element_by_id("mat-input-1").send_keys(psw)
        self.driver.find_element_by_id("mat-input-1").send_keys(Keys.ENTER)
        sleep(15)
    #验证登陆是否成功,找一个登陆后才有的元素,这里我随便写的
    def is_login_sucess(self):
        try:
            text = self.driver.find_element_by_id("myblog_icon").text
            print(text)
            return True
        except:
            return False
    #用例部分
    def test_login_1(self):
        self.login("1923501505@qq.com","******")
        result = self.is_login_sucess()
        self.assertTrue(result)
    def test_login_2(self):
        self.login("1923501505@qq.com","******")
        result = self.is_login_sucess()
        self.assertTrue(result)
    def test_login_3(self):
        self.login("1923501505@qq.com","******")
        result = self.is_login_sucess()
        self.assertTrue(result)
    #退出浏览器
    def setDown(self):
        self.driver.quit()
#执行
if __name__ == "__main__":
    unittest.main()

案例三

创建项目

创建一个项目,在该项目下创建以下几个py文件
在这里插入图片描述
被测对象:myClass.py
测试用例:Test_Myclass.py Test_Myclass2.py
运行用例:main.py main1.py main2.py

被测对象

#这里定义了一个类,用与计算加法与减法
class Math:
    def add(self, a, b):
        return a + b
    def minus(self, a, b):
        return a - b

测试用例

import unittest
#调用被测对象
from myClass import Math

class Test_MyClass(unittest.TestCase):
    
    #如果在setUp里实例化被测文件中的类,那么每一条测试用例都要实例化一次被测类,用setUpClass()
    #可以只实例化一次,同理,tearDownClass也只做一次收尾工作
    @classmethod
    def setUpClass(cls):
        cls.m = Math()
    @classmethod
    def tearDownClass(cls):
        pass

    # 被测文件中的类,注意测试用例是以test_开头
    #测试用例的执行顺序是以字母a-z和数字的从小到大的顺序来排列的,可以在test_后面加数字,控制运行顺序
    def test_2add(self):  #加法
        result = self.m.add(100, 23)
        print("我先执行")
        self.assertEqual(123, result)
    def test_1minus(self):  #减法
        result = self.m.minus(235, 111)
        print("我后执行")
        self.assertEqual(124, result)  #断言
#私有属性,可单独运行,其他py文件不可调用
if __name__ == "__main__":
    unittest.main()

unittest进阶使用

一)main.py

import unittest
from Test_Myclass import Test_MyClass  #调用Test_Myclass.py文件

#实例化被测对象
s = unittest.TestSuite()

#调用addTest来加载测试用例  addTest(类名("用例函数名称"))——添加一个测试用例
#方法1
s.addTest(Test_MyClass("test_2add"))
s.addTest(Test_MyClass("test_1minus"))
#方法2
s.addTests([Test_MyClass("test_2add"),Test_MyClass("test_1minus")])

#使用TextTestRunner来运行测试用例
fs = open("test_run_result.txt","w") #打开一个文件
#实例化  输出测试报告到文件
#runner = unittest.TestRunner()
runner = unittest.TextTestRunner(fs)
#用run方法就是用来运行测试用例的
runner.run(s)

二)main1.py
unittest.TestLoader.discover方法匹配目录下的用例

import os
import unittest
#实例化测试套件对象
s = unittest.TestSuite()
#1.实例化TestLoader对象  2.使用discover去找到一个目录下的所有测试用例
loader = unittest.TestLoader()
#3.使用addTests将找到的测试用例放在测试套件下  4.os.getcwd()方法用于返回当前工作目录。
s.addTests(loader.discover(os.getcwd()))
#运行
runner = unittest.TextTestRunner()
runner.run(s)

三)main2.py
html报告

import unittest, os, time
from HTMLTestRunner import HTMLTestRunner

#实例化测试套件对象
s = unittest.TestSuite()
#1.实例化TestLoader对象  2.使用discover去找到一个目录下的所有测试用例
loader = unittest.TestLoader()
#3.使用addTests将找到的测试用例放在测试套件下
s.addTests(loader.discover(os.getcwd()))

#获取当前时间
curTime = time.strftime("%Y-%m-%d_%H-%M-%S")
#在当前目录下创建一个html文件
fp = open(os.getcwd() + "/autoTest_report_{0}.html".format(curTime), "wb")

#运行测试用例,生成测试报告
runner = HTMLTestRunner(
        stream=fp,
        title="单元测试报告",
        description="Math类的单元测试报告"
)
runner.run(s)
# -*- coding: utf-8 -*-
from selenium import webdriver
from HTMLTestRunner import HTMLTestRunner
import unittest
import time


class BaiduIdeTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "https://www.baidu.com/"

    def test_baidu_ide(self):
        driver = self.driver
        driver.get(self.base_url)
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys("HTMLTestRunner")
        driver.find_element_by_id("su").click()
        time.sleep(5)
        self.assertEqual(u"HTMLTestRunner_百度搜索", driver.title)

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


if __name__ == "__main__":
    # 构造测试套件
    testsuit = unittest.TestSuite()
    testsuit.addTest(BaiduIdeTest("test_baidu_ide"))
    # 定义测试报告存放路径
    fp = open('./result1.html', 'wb')
    # 定义测试报告
    runner = HTMLTestRunner(stream=fp,
                            title='自动化测试报告',
                            description='用例执行情况:')
    runner.run(testsuit)
    # 关闭测试报告
    fp.close()

二次封装

元素定位参数化(find_element)

#encoding:utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.find_element(By.ID,"kw").send_keys("python")
sleep(3)
driver.find_element(By.ID,"su").click()
sleep(3)
driver.quit()
#encoding:utf-8
from selenium import webdriver
#from selenium.webdriver.common.by import By
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.find_element("id","kw").send_keys("python")
sleep(3)
driver.find_element("id","su").click()
sleep(3)
driver.quit()

# by_id= "id"
# by_xpath = "xpath"
# by_link_text = "link text"
# by_partial_text = "partial link text"
# by_name = "name"
# by_tag_name = "tag name"
# by_class_name = "class name"
# by_css_selector = "css selector"

登陆方法参数化

from selenium import webdriver
from time import sleep
from HTMLTestRunner import HTMLTestRunner
#导入键盘操作模块
from selenium.webdriver.common.keys import Keys
import unittest
class Blog(unittest.TestCase):
    #登陆网站
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.cnblogs.com/")
    #参数化登陆账号密码
    def login(self,username,psw):
        self.driver.find_element("xpath","//*[@id='navbar_login_status']/a[4]").click()
        self.driver.find_element("id","mat-input-0").send_keys(username)
        self.driver.find_element("id","mat-input-1").send_keys(psw)
        self.driver.find_element("id","mat-input-1").send_keys(Keys.ENTER)
        sleep(15)
        self.driver.find_element_by_xpath("//*[@id='myblog_icon']").click()
    #判断登陆是否成功
    def is_login_sucess(self):
        try:
            text = self.driver.find_element("id", "Header1_HeaderTitle").text
            print(text)
            return True
        except:
            return False
    #用例部分
    def test_login_1(self):
        self.login("1923501505@qq.com","****")  #调用登陆方法
        result = self.is_login_sucess()  #判断结果
        self.assertTrue(result)
    # def test_login_2(self):
    #     self.login("1923501505@qq.com","****")
    #     result = self.is_login_sucess()
    #     self.assertTrue(result)
    # def test_login_3(self):
    #     self.login("1923501505@qq.com","****")
    #     result = self.is_login_sucess()
    #     self.assertTrue(result)
    #退出浏览器
    def setDown(self):
        self.driver.quit()
if __name__ == "__main__":
    # 构造测试套件
    suit = unittest.TestSuite()
    suit.addTest(Blog("test_login_1"))
    # 定义测试报告存放路径
    fp = open('./result7712.html', 'wb')
    # 定义测试报告
    runner = HTMLTestRunner(stream=fp,
                            title='自动化测试报告',
                            description='用例执行情况:')
    runner.run(suit)
    # 关闭测试报告
    fp.close()

不会生成html报告原因

PyCharm会默认使用自带的unittest框架来执行单元测试,不会执行main函数中的代码,所以不生成测试报告,所以你直接执行上面的代码会有问题
解决方案如下
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

异常处理(NoSuchElementException)

案例(一)

#encoding = utf-8
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
dr = webdriver.Chrome()
dr.get("https://www.baidu.com")
try:
    element = dr.find_element("id","s1u")
except NoSuchElementException as msg:
    print("查找元素异常:{}".format(msg))
    print("查找元素异常:%s"%msg)
    dr.quit()
else:
    element.click()
    dr.quit()

常见异常:
1.NoSuchElementException:没有找到元素

2.NoSuchFrameException:没有找到iframe

3.NoSuchWindowException:没找到窗口句柄handle

4.NoSuchAttributeException:属性错误

5.NoAlertPresentException:没找到alert弹出框

6.ElementNotVisibleException:元素不可见

7.ElementNotSelectableException:元素没有被选中

8.TimeoutException:查找元素超时

不导入异常模块 Exception

#encoding = utf-8
from selenium import webdriver
dr = webdriver.Chrome()
dr.get("https://www.baidu.com")
try:
    element = dr.find_element("id","s1u")
except Exception as msg:
    print("查找元素异常:{}".format(msg))
    print("查找元素异常:%s"%msg)
    dr.quit()
else:
    element.click()
    dr.quit()

Excel处理

当登录的账号有多个的时候,我们一般用 excel 存放测试数据,python 读取 excel 方法,并保存为字典格式。
准备:安装xlrd
pip install xlrd
在这里插入图片描述

import xlrd
# 打开 exlce 表格,参数是文件路径
data = xlrd.open_workbook("C:\\Users\\Administrator\\Desktop\\xlrd.1")

#获取表单
#通过索引顺序获取
table = data.sheets()[0]
table = data.sheet_by_index(0)
#通过名称获取
table = data.sheet_by_name(u"Sheet1")

#获取表单中的一些数据
# 获取总行数
nrows = table.nrows
# 获取总列数
ncols = table.ncols

# 获取一行或一列的值,参数是第几行
table.row_values(0) # 获取第一行值
table.col_values(0) # 获取第一列值

"""
在excel中存放数据,第一行为标题,也就是对应字典里面的key值,如:username,password 
如果 excel 数据中有纯数字的一定要右键->设置单元格格式->文本格式,要不然读取的数据是浮点数 
"""
#encoding:utf-8
import xlrd
class ExcelUtil():
    def __init__(self,excelPath,sheetName):
        self.data = xlrd.open_workbook(excelPath)
        self.table = self.data.sheet_by_name(sheetName)
        #获取第一行作为key值
        self.keys = self.table.row_values(0)
        #获取总行数
        self.rowNum = self.table.nrows
        #获取总列数
        self.colNum = self.table.ncols
    def dict_data(self):
        if self.rowNum <= 1:
            print("总行数小于一")
        else:
            r = []
            j = 1
            for i in range(self.rowNum-1)
                s = {}
                #从第二行开始取对应的value值
                values = self.table.row_values(j)
                for x in range(self.colNum)
                    s[self.keys[x]] = values[x]
                r.append(s)
                j = j + 1
            return r
if __name__ == "__main__":
    filepath = "C:\\Users\\Administrator\\Desktop\\xlrd.1"
    sheetName = "Sheet1"
    data = ExcelUtil(filepath, sheetName)
    print(data.dict_data())

不对,这个xlrd库不好用

补充知识,使用openpyxl库处理excel

案例一、

import openpyxl
#创建excel工作薄
wb = openpyxl.Workbook()
#创建一个表单
wb.create_sheet("test_case")
#保存为xlsx的文件
wb.save("cases.xlsx")

# 读取excel中的数据
# 第一步:打开工作簿
wb = openpyxl.load_workbook("cases.xlsx")
#第二步:选取表单
sh = wb["test_case"]
# 第三步:读取数据
# 参数 row:行  column:列
ce = sh.cell(row=1,column=1)
print(ce.value)

print(list(sh.rows)[1:])     # 按行读取数据,去掉第一行的表头信息数据
#一行一行的遍历
for cases in list(sh.rows)[1:]:# 读取第一行,第一列的数据
    case_id =  cases[0].value
    case_excepted = cases[1].value
    case_data = cases[2].value
    print(case_id,case_excepted,case_data)
# 关闭工作薄
wb.close()

在这里插入图片描述
在这里插入图片描述

案例二、

按行读取数据,存储在列表中

import openpyxl
class Case: #这个类用来存储用例的
    __slots__ = [] #特殊的类属性,可以用来限制这个类创建的实例属性添加 可写可不写
    pass

class ReadExcel(object): #读取excel数据的类
    def __init__(self,file_name,sheet_name):
        """
        这个是用来初始化读取对象的
        :param file_name: 文件名 ---> str类型
        :param sheet_name: 表单名 ———> str类型
        """
        # 打开文件
        self.wb = openpyxl.load_workbook(file_name)
        # 选择表单
        self.sh = self.wb[sheet_name]
    def read_data_line(self):
        #按行读取数据转化为列表
        rows_data = list(self.sh.rows)
        # print(rows_data)
        # 获取表单的表头信息
        titles = []
        for title in rows_data[0]:
            titles.append(title.value)
        # print(titles)
        #定义一个空列表用来存储测试用例
        cases = []
        for case in rows_data[1:]:
            # print(case)
            data = []
            for cell in case: #获取一条测试用例数据
                # print(cell.value)
                data.append(cell.value)
                # print(data)
                #判断该单元格是否为字符串,如果是字符串类型则需要使用eval();如果不是字符串类型则不需要使用eval()
                #eval()函数用来执行一个字符串表达式,并返回表达式的值。
                #isinstance()函数来判断一个对象是否是一个已知的类型
                if isinstance(cell.value,str):
                    data.append(eval(cell.value))
                else:
                    data.append(cell.value)
                #将该条数据存放至cases中
            # print(dict(list(zip(titles,data))))
            #zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表
                """
                x = [1, 2, 3]
                y = [4, 5, 6]
                z = [7, 8, 9]
                xyz = zip(x, y, z)
                print xyz
                运行的结果是:
                [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
                """
                case_data = dict(list(zip(titles,data)))
                cases.append(case_data)
        return cases
if __name__ == '__main__':
    r = ReadExcel('cases.xlsx','Sheet1')
    data1 = r.read_data_line()
    print(data1)

案例三、

按行读取数据,存储在对象中

import openpyxl
class Case:
    pass
class ReadExcel(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sh = self.wb[sheetname]
    def read_data_obj(self):
        """
        按行读取数据  每条用例存储在一个对象中
        :return:
        """
        rows_data = list(self.sh.rows)
        # print(rows_data)
        # 获取表单的表头信息
        titles = []
        for title in rows_data[0]:
            titles.append(title.value)
        # print(titles)
        # 定义一个空列表用来存储测试用例
        cases = []
        for case in rows_data[1:]:
            # print(case)
            #创建一个Case类的对象,用来保存用例数据
            case_obj = Case()
            data = []
            for cell in case:  # 获取一条测试用例数据
                # print(cell.value)
                # data.append(cell.value)
                # print(data)
                if isinstance(cell.value,str):  # 判断该单元格是否为字符串,如果是字符串类型则需要使用eval();如果不是字符串类型则不需要使用eval()
                    data.append(eval(cell.value))
                else:
                    data.append(cell.value)
            # 将该条数据存放至cases中
            # print(dict(list(zip(titles,data))))
            case_data = list(zip(titles, data))
            # print(case_data)
            for i in case_data:
                setattr(case_obj,i[0],i[1])
            # print(case_obj)
            # print(case_obj.case_id,case_obj.data,case_obj.excepted)
            cases.append(case_obj)
        return cases
if  __name__ == '__main__':
    r = ReadExcel('cases.xlsx','Sheet1')
    res = r.read_data_obj()
    for i in res:
        print(i.caseid, i.excepted, i.data)

案例四、

将测试用例封装到列表中,读取指定列的数据

import openpyxl
class Case:
    pass
class ReadExcelZy(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]
        # list1 参数为一个列表,传入的是指定读取数据的列,比如[1,2,3]
        # 每一行[1,3,5]列的数据,读取出来就作为一条测试用例,放在字典中
        # 所有的用例放在列表中并且进行返回
    def read_data(self,list1):
        """
        :param list1:  list--->要读取列   list类型
        :return:    返回一个列表,每一个元素为一个用例(用例为dict类型)
        """
        # 获取最大的行数
        max_r = self.sheet.max_row
        cases = []   #定义一个空列表,用来存放所有的用例数据
        titles = []   #定义一个空列表,用来存放表头
        # 遍历所有的行数据
        for row in range(1,max_r+1):
            if row != 1:      #判断是否是第一行
                case_data = [] #定义一个空列表,用来存放该行的用例数据
                for column in list1:
                    info = self.sheet.cell(row,column).value
                    # print(info)
                    case_data.append(info)
                    # print(list(zip(titles,case_data)))
                case = dict(zip(titles,case_data))  #将该条数据和表头进行打包组合,作用相当于dict(list(zip(titles,case_data)))
                # print(case)
                cases.append(case)
                # print(cases)
            else:   #获取表头数据
                for column in list1:
                    title = self.sheet.cell(row,column).value
                    titles.append(title)
                # print(titles)
        return cases
if __name__ == '__main__':
    r = ReadExcelZy("cases.xlsx","Sheet1")
    res = r.read_data([1,2,3])
    for o in res:
        print(o['caseid'],o['data'],o['excepted'])

案例五、

将测试用例封装到对象中,读取指定列的数据

import openpyxl
class Case:
    pass
class ReadExcelZy(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]

        # list1 参数为一个列表,传入的是指定读取数据的列,比如[1,2,3]
        # 每一行[1,3,5]列的数据,读取出来就作为一条测试用例,放在字典中
        # 所有的用例放在对象中并且进行返回
    def read_data_obj(self,list2):
        max_r1 = self.sheet.max_row      #获取最大行数
        cases = []
        titles = []      #用来存放表头数据
        for row in range(1,max_r1+1):
            if row != 1:
                case_data = []
                for column in list2:
                    info = self.sheet.cell(row,column).value
                    # print(info)
                    case_data.append(info)
                cases_data = list(zip(titles,case_data))
                #将一条用例存到一个对象中(每一列对应对象的一个属性)
                case_obj = Case()
                for i in cases_data:
                    # print(i)
                    setattr(case_obj,i[0],i[1])
                # print(case_obj.caseid,case_obj.excepted,case_obj.data)
                cases.append(case_obj)
            else:
                for column in list2:
                    title = self.sheet.cell(row,column).value
                    titles.append(title)
        return cases
if __name__ == '__main__':
    r = ReadExcelZy("cases.xlsx","Sheet1")
    res = r.read_data_obj([1,2,3])
    for i in res:
        print(i.caseid,i.data,i.excepted)

案例六、

优化案例五部分代码,将设置对象属性写在初始化方法中(封装Excel类读取数据最常用的方法)

import openpyxl
class Case:  # 这个类用来存储用例的
    def __init__(self, attrs):
        """
        初始化用例
        :param attrs:zip类型——>[{key,value},(key1,value1)......]
        """
        for i in attrs:
            setattr(self, i[0], i[1])
class ReadExcel(object):
    def __init__(self, filename, sheetname):
        """
        定义需要打开的文件及表名
        :param filename:   文件名
        :param sheetname:  表名
        """
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]
    def read_data_obj_new(self, list2):
        # 获取最大行数
        max_r1 = self.sheet.max_row
        cases = []
        # 用来存放表头数据
        titles = []
        for row in range(1, max_r1 + 1):
            if row != 1:
                case_data = []
                for column in list2:
                    info = self.sheet.cell(row, column).value
                    # print(info)
                    case_data.append(info)
                case = list(zip(titles, case_data))
                # 新建对象时,将对象传给Case类
                case_obj = Case(case)
                # print(case_obj.caseid,case_obj.excepted,case_obj.data)
                cases.append(case_obj)
            else:
                # 获取表头
                for column in list2:
                    title = self.sheet.cell(row, column).value
                    titles.append(title)
                if None in titles:
                    raise ValueError("传入的表头的数据有显示为空")
        return cases
if __name__ == '__main__':
    r = ReadExcel('cases.xlsx', 'Sheet1')
    res1 = r.read_data_obj_new([1, 2, 3])
    for i in res1:
        print(i.caseid, i.data, i.excepted)

案例七、

将测试数据参数化

import unittest
from python.register_new.register import register
from python.register_new.register_testcase_new import RegisterTestCase
from HTMLTestRunnerNew import HTMLTestRunner
class RegisterTestCase(unittest.TestCase):
    # 初始化测试用例
    def __init__(self,modethod_name,excepted,data):
        # modethod_name 测试用例方法名
        super().__init__(modethod_name)
        # excepted 测试用例的预期结果
        self.excepted = excepted
        # data 测试用例参数值
        self.data = data

    def setUp(self):
        print("准备测试环境,执行测试用例之前会执行此操作")

    def tearDown(self):
        print("还原测试环境,执行完测试用例之后会执行此操作")

    def test_register(self):
        res = register(*self.data)
        try:
            self.assertEquals(self.excepted,res)
        except AssertionError as e:
            print("该条测试用例执行未通通过")
            raise e
        else:
            print("该条测试用例执行通过")

# 创建测试套件
suite = unittest.TestSuite()

# 将测试用例添加至测试套件中
case = [{'excepted':'{"code": 1, "msg": "注册成功"}','data':'('python1', '123456','123456')'},
        {'excepted':'{"code": 0, "msg": "两次密码不一致"}','data':'('python1', '1234567','123456')'}]
for case in cases:
    suite.addTest(RegisterTestCase('test_register',case['excepted'],case['data']))

# 执行测试套件,生成测试报告
with open("report.html",'wb') as f:
    runner = HTMLTestRunner(
        stream = f,
        verbosity = 2,
        title = 'python_test_report',
        description = '这是一份测试报告',
        tester = 'WL'
    )
    runner.run(suite)

案例八、

将调用封装好的Excel类的完整代码流程

import unittest
from python.register_new.register import register
from python.register_new.register_testcase_new import RegisterTestCase
from HTMLTestRunnerNew import HTMLTestRunner
from python.readexcel import ReadExcel


class RegisterTestCase(unittest.TestCase):
    # 初始化测试用例
    def __init__(self, modethod_name, excepted, data):
        # modethod_name 测试用例方法名
        super().__init__(modethod_name)
        # excepted 测试用例的预期结果
        self.excepted = excepted
        # data 测试用例参数值
        self.data = data

    def setUp(self):
        print("准备测试环境,执行测试用例之前会执行此操作")

    def tearDown(self):
        print("还原测试环境,执行完测试用例之后会执行此操作")

    def test_register(self):
        res = register(*self.data)
        try:
            self.assertEquals(self.excepted, res)
        except AssertionError as e:
            print("该条测试用例执行未通通过")
            raise e
        else:
            print("该条测试用例执行通过")


# 创建测试套件
suite = unittest.TestSuite()
# 调用封装好的读取数据的Excel类,获取测试数据
r1 = ReadExcel('cases.xlsx', 'Sheet1')
cases = r1.read_data_obj_new([2, 3])
# 将测试用例添加至测试套件中
for case in cases:
    # 需要使用eval()函数对except和data进行自动识别
    suite.addTest(RegisterTestCase('test_register', eval(case.excepted), eval(case.data)))
# 执行测试套件,生成测试报告
with open("report.html", 'wb') as f:
    runner = HTMLTestRunner(
        stream=f,
        verbosity=2,
        title='python_test_report',
        description='这是一份测试报告',
        tester='WL')
    runner.run(suite)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小桃子的思念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值