提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:学完本篇文章,自动化测试算是入门了
提示:以下是本篇文章正文内容,下面案例可供参考
1、python3.7
2、pycharm
3、selenium
4、xpath与chrome控件
selenium下载
cmd窗口下输入:pip install selenium
版本问题可能导致安装失败
chrome控件放入python安装的根目录
下载地址:http://chromedriver.storage.googleapis.com/index.html
请与chrome浏览器的版本相对应,否则无法启动
1.点击(鼠标左键)页面按钮:click()
2.请空输入框:clear()
3.输入字符串:send_keys()
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()
有些页面的链接打开后,会重新打开一个窗口,对于这种情况,想在新页面上操作,就得先切换窗口了。获取窗口的唯一标识用句柄表示,所以只需要切换句柄,我们就能在多个页面上灵活自如的操作了。
本篇以打开百度新闻页面搜索按钮上的链接页面为例,依次打开每个按钮,并检验测试结果。用脚本批量操作,可以减少重复劳动,重复的事情让脚本去执行吧!
1.打开百度新闻页面:17http://news.baidu.com/17
3.当点击百度新闻页面上新闻时,会打开一个新的窗口
3.人为操作的话,可以通过点击窗口切换到不同的窗口上,但是脚本它不
知道你要操作哪个窗口,这时候只能获取窗口唯一的标识:句柄
4.获取当前页面的句柄:driver.current_window_handle
5.获取所有窗口的句柄:driver.window_handles
有很多小伙伴在拿 163 作为登录案例的时候,发现不管怎么定位都无法定位到,到底是什么鬼呢,下面详细介绍 iframe 相关的切换
frame 与 iframe 两者可以实现的功能基本相同,不过 iframe 比 frame 具有更多的灵活性。 frame 是整个页面的框架,iframe 是内嵌的网页元素,也可以说是内嵌的框架
iframe 标记又叫浮动帧标记,可以用它将一个 HTML 文档嵌入在一个 HTML中显示。它和 Frame 标记的最大区别是在网页中嵌入 的所包含的内容与整个页面是一个整体,而< /frame>所包含的内容是一个独立的个体,是可以独立显示的。另外,应用 iframe 还可以在同一个页面中多次显示同一内容,而不必重复这段内容的代码。
iframe 的切换是默认支持 id 和 name 的方法的
界面改版,提供老版本百度下拉框定位方式,主要是为了了解流程,现版本不可用
选项有三个
不是所有的弹出框都叫 alert,在使用 alert 方法前,先要识别出到底是不是alert。先认清楚 alert 长什么样子,下次碰到了,就可以用对应方法解决。
alert\confirm\prompt 弹出框操作主要方法有:
text:获取文本值
accept() :点击"确认"
dismiss() :点击"取消"或者叉掉对话框
send_keys() :输入文本值 --仅限prompt,在 alert 和 confirm 上没有输入框
<html>
<head>
<title>Alerttitle>
head>
<body>
body>
html>
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() #退出弹出框
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() #退出弹出框,相当于取消按钮
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>
<input id="c1" type="checkbox">selenium<br>
<input id="c2" type="checkbox">python<br>
<input id="c3" type="checkbox">appium<br>
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() #点击单选
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()
源码
<meta charset="UTF-8">
<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>123456td>
<td>httd>
tr>
<tr>
<td>appium 自动化td>
<td>123456789td>
<td>httd>
tr>
table>
body>
html>
1.table 页面查看源码一般有这几个明显的标签:table、tr、th、td
2.<table>标示一个表格
3.<tr>标示这个表格中间的一个行
4.</th> 定义表头单元格
5.</td> 定义单元格标签,一组<td>标签将建立一个单元格,<td>标签必须放在<tr>标签内
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("[email protected]")
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 = 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 方法可以获取到页面源码。
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)
#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 相关操作在平常 ui 自动化中用得少,偶尔也会用到,比如登录有图形验证码,可以通过绕过验证码方式,添加 cookie 方法登录。
登录后换账号登录时候,也可作为后置条件去删除 cookie 然后下个账号登录
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)
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)
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的一部分
.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() #这里刷新后发现用户已登录,亲测有效
有些特殊的操作 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)
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.12306.cn/")
sleep(2)
"""
"""
#去掉元素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")
页面源码
<meta charset="UTF-8">
<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
打开cmd窗口,输入python -m pydoc -p 10000
浏览器输入网址:http://localhost:10000/
python 的单元测试框架,是基于 java 的 junit 测试框架。
# 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()
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树下移除,返回True或False
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 |
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()
一)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()
#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()
PyCharm会默认使用自带的unittest框架来执行单元测试,不会执行main函数中的代码,所以不生成测试报告,所以你直接执行上面的代码会有问题
解决方案如下
案例(一)
#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 存放测试数据,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库不好用
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)