-
自动化测试基础
-
自动化测试概述
-
自动化测试工具
-
自动化测试前景
-
-
selenium基础
-
selenium概述
- selenium的组成:
- selenlum 1.0 :selenlum IDE. selenlum rC、selenlum grld
- selenium 2.0 :selenium IDE、selenium rC. webdriver. selenium grid
- selenium IDE: UI用户界面的脚本录制工具(不用写脚本,只需要点点就能生成脚本),毕竟能够处理的逻辑有限,对于复杂的脚本处理起来很麻烦,除非刚入门不会写代码,可以录制简单的脚本,再或者,可以使用其录制一个基本的脚本,然后去修改其逻辑,采用的关键字驱动的方式进行脚本开发的。
- selenlum RC: c/s
- c: java/python开发的脚本
s:浏览器
- c: java/python开发的脚本
- webdriver:包(各种模块) .对浏览器的apl (对浏览器中元素或者浏览器的操作)。替代rc
- 为什么替代?主要是webdriver对浏览器的调度效本提高了好多
- selenium3.0: selenium IDE. webdriver. selenium grid
- selenium IDE:完整的集成开发环境
- selenium grid:分布式测试,一个脚本可以在同时在不同的os及浏览器中运行
- selenium的组成:
-
Selenium IDE工具的使用
- firefox浏览器的插件,只需要在ff的附加组件中添加selenium ide即可
- 使用selenium ide
- Record a new test in a new project
- 录制一个新的测试在新的工程中(自动化测试的项目作为工程,一个工具的功能可以作为一个测试)
- Open an existing project
- 原来已经开发好了,只需要打开对应的工程文件即可
- Create a new project
- 创建一个新的空工程
- Close Selenium IDE
- 关闭selenium IDE工具
- Record a new test in a new project
- 脚本录制
- 在浏览器中手动操作,selenium就可以把脚本录制出来
- 生成的代码是以关键字驱动:主谓宾语法
- Target:对谁进行操作?可以使用它们的属性进行定位
- Command:找到之后,要对他干嘛?输入、键入
- Value:键入啥?abc
- 录制完之后,需要把脚本的步骤列表中,不需要的步骤可以删除
- 一个完整的测试用例,应该包括哪些内容:步骤(command,target,value)、断言(实际对比)
- 断言要求:不需要多,一个就够了,只要能够唯一确定脚本是通过的即可
- 断言页面显示文本:assert text、
- 运行脚本
- 点击运行按钮,查看日志,看所有步骤是否ok,断言是否ok,是否出现最终的结果“*** completed successfully”如果都可以,则该脚本运行通过
- 导出功能
- python+pytest
-
Katalon工具
- 和seleniumIDE功能类似的工具,可以到处python+unittest的脚本
- 在firefox中添加katalon Record组件
- 使用Katalon工具
- 测试集testsuite:存放测试用例脚本的文件夹
-
Selenium测试环境搭建
- python+selenium
- 1.python3安装并配置环境变量
- 2.selenium安装
- cmd直接输入 pip3 install selenium
- 3.浏览器驱动安装:
- 由于执行的脚本需要浏览器驱动来驱动浏览器,要安装相应的浏览器驱动
- WebDriver支持firefox、IE、Opera、Chrome等浏览器
- https://selenium.dev/documentation/en/getting_started_with_webdriver/third_party_drivers_and_plugins/
- 将驱动添加至系统环境变量Path下,或添加至python根目录(python已添加之系统环境变量)
-
#导包 from selenium import webdriver #创建浏览器对象 driver = webdriver.Chrome() #打开百度首页 driver.get("https://www.baidu.com") #在百度的文本框中输入selenium driver.find_element_by_id("kw").send_keys("selenium") #点击百度按钮 driver.find_element_by_id("su").click() #关闭浏览器 driver.quit()
-
-
WebDriver API
-
页面元素定位、操作
-
页面元素:
- 在浏览器中能显示的所有的要素,如图片、文本框、按钮、下拉列表、视频等
- 自动化
- 代码控制浏览器中的元素,让这些元素“动”起来(按照脚本设计逻辑执行)
- 自动化测试的主要步骤
- 1.通过某些方式定位到我们要执行的对象、目标target
- 2.对这个对象进行什么操作command
- 3.通过操作对定位到的元素赋值value
- 4.添加断言操作
- webdriver提供的定位元素的方式:
-
WebDriver元素定位方式 对应的python方法 id find_element_by_id("id属性值") name find_element_by_name("name属性值") class name find_element_by_class_name("id值") tag name find_element_by_tag_name(“标签名“)
link text find_element_by_link_text(“链接的显示文本”) partial link text find_element_by_partial_link_text(”部分链接的西安市文本“) xpath find_element_by_xpath(”xpath“) css selector find_element_by_css_selector() -
需求:在百度文本框输入selenium,点击百度一下
1.百度文本框
2.百度一下
使用ID属性定位:
1.确定要操作的对象
2.获取id属性(kw\su)
3.其他操作
#导包、创建浏览器对象、获取一下ur1地址
form selenium import webdriverimport time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")find_by_id #通过ID定位文本框和百度一下
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(2)
driver.find_element_by_id("su").click()
time.sleep(2)#关闭浏览器
driver.quit()find_by_name #通过name属性定位元素
driver.find_element_by_name("wd").send_keys("selenium")
time.sleep(2)
driver.find_element_by_id("su").click()
time.sleep(2)
driver.quit()
find_by_class_name #通过classname属性定位元素
driver.find_element_by_class_name("s_ipt").send_keys("selenium")
time.sleep(2)
driver.find_element_by_class_name("s_btn").click()
time.sleep(2)
driver.quit()
find_by_tag_name
#通过tagname属性定位元素
driver.find_element_by_tag_name("input").send_keys("selenium")
time.sleep(2)
driver.find_element_by_class_name("s_btn").click()
time.sleep(2)
driver.quit()
find_by_link_text
find_by_partial_link_text
需求:定位百度首页上的”新闻链接,并打开新闻页面“
#通过link text属性定位元素
#(元素显示的文本信息,要求是全部信息)
driver.find_element_by_link_name("新闻").click()
#通过partial link text属性定位元素
#(元素显示的文本信息,可以是部分信息)
#等待三秒
time.sleep(3)
driver.quit()
xpath定位
绝对路径定位
/:根节点
//:相对节点
百度文本框对应的绝对路径:
父节点使用/链接(在树状结构上有明显的所属关系)
同标签名的节点是兄弟节点,使用[]排名次,
/html/body/div/div/div[3]/div/div/form/span/input
/html/body/div/div/div[3]/div/div/form/span[2]/input
driver.find_element_by_xpath("/html/body/div/div/div[3]/div/div/form/span/input").send_keys("selenium")
time.sleep(5)
driver.find_element_by_xpath("/html/body/div/div/div[3]/div/div/form/span[2]/input").click()
time.sleep(5)
利用元素属性定位:
//input[@id='kw']
driver.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
time.sleep(2)
driver.find_element_by_xpath("//input[@id='su']").click()
time.sleep(2)
利用父子关系以及属性定位:
百度文本框按钮,当前属性都不好定位,但是她父亲(爷爷)的属性比较好定
父子关系定位到相应的元素(文本框)
//form[@id='form']/span/input
//form[@id='form']/span[2]/input
driver.find_element_by_xpath("//form[@id='form']/span/input").send_keys("selenium")
time.sleep(2)
driver.find_element_by_xpath("///form[@id='form']/span[2]/input").click()
time.sleep(2)
使用逻辑运算符:
通过一个元素属性无法定位,有重复的,一个不行来两个
元素a:id=1,name=a
元素b:id=1,name=b
元素c:id=2,name=a
若想定位元素a,使用and和or运算符
driver.find_element_by_xpath("//input[@id='kw' and @name='wd']").send_keys("selenium")
time.sleep(2)
driver.find_element_by_xpath("//input[@id='su']").click()
time.sleep(2)
直接浏览器复制:
//input[@id="kw"]
//*[@id="u1"]/a[2]
css定位 #css的类选择器定位百度文本框,使用css的id选择器定位拜读一下按钮
driver.find_element_by_xpath(".s_ipt").send_keys("selenium")
driver.find_element_by_xpath("#su").click()
time.sleep(3)
driver.quit()222
-
- 操作:或单击(按钮),或输入(输入框)
- clear():清除文本
- send_keys(value):模拟按键输入,除了能够发送字母外,还可以发送快捷键
- click():单击元素,例如按钮、超链接、单选框、复选框
- Current_url:返回当前页面的url地址
- title:返回当前页面的title
- Text:获取页面(提示框、警告框)显示的文本
- 需求:获取百度首页下二维码的描述信息:有事搜一搜 没事看一看
- 定位://*[@id="qrcode"]/div/div[2]/p[2]
- 操作:获取元素的文本.text
-
#获取文本
wenben = driver.find_element_by_xpath("//*[@id="qrcode"]/div/div[2]/p[2]").text
print(wenben)
#获取二维码下的显示文本
wenben = driver.find_element_by_xpath('//*[@id="bottom_layer"]/div[1]').text
print(wenben)
- 需求:获取百度首页下二维码的描述信息:有事搜一搜 没事看一看
- get_attribute(name):获得属性值,文本框中的值使用value属性名
-
#获取百度文本框的name属性
value1 = driver.find_element_by_id("kw").get_attribute("value")
value2 = driver.find_element_by_id("su").get_attribute("class")
print(value1)
-
- is_displayed():设置该元素是否用户可见
-
#判断百度一下按钮是否显示出来了
if driver.find_element_by_id("su").is_displayed();
print("正常显示了百度一下")
else
print("显示失败")
-
- is_enabled():判断是否可用
-
is_selected():判断是否选中,一般用复选框或者单选框的判断
-
-
浏览器操作
- 控制浏览器窗口大小
- Set_window_size()
- 控制浏览器后退、前进
- back():后退
- forward():前进
- 模拟浏览器刷新
- WebDriver提供了refresh()方法
- 截屏操作
- driver.save_screenshot(r"e:\abc.png")
- 模拟浏览器关闭
- close():关闭单个页面
- quit():关闭所有页面
-
#导包、创建浏览器对象、获取一下ur1地址
form selenium import webdriverimport time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")#比较喜欢宽屏显示,设置打开窗口为1080*600
#driver是浏览器对象
#windowHandle:一个页面的标识
driver.set_window_size(1080,600)
#最大化显示窗口
driver.maximize_window()
#最小化显示窗口
driver.minimize_window()
#页面的前进后退操作
driver.find_element_by_link_text("新闻").click()
time.sleep(2)
#后退到百度首页
driver.back()
time.sleep(2)
#再前进到新闻页面
driver.forward()
time.sleep
#再执行依次刷新操作
driver.refresh()
#截屏一般要加判断 什么时候要截什么时候不截
driver.find_element_by_link_text("新闻").click()
driver.save_screenshot(r"e:\abc.png")
driver.save_screenshot_as_file(r"e:\abc.png")
driver.save_screenshot_as_file("{}.{}".format(r"e:\abc","png"))
time.sleep(3)
关闭功能
driver.quit()
- 控制浏览器窗口大小
-
鼠标、键盘操作
-
鼠标事件
- click()是模拟鼠标的单机操作。web产品中更丰富的交互方式,鼠标右击、双击、悬停甚至鼠标拖动。
- WebDriver中封装在ActionChains类中,
- 导入from selenium.webdriver.common.action_chains import ActionChains
- 常见方法:
- perform():执行所有ActionChains中存储的行为
- context_click():右击
- double_click():双击
- drag_and_drop():拖动
- move_to_element():鼠标悬停
-
#导包、创建浏览器对象、获取一下ur1地址
form selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")time.sleep(2)
#控制鼠标悬浮在“设置“按钮上
setButton = driver.find_element_by_link_text("设置")
#将对”设置“按钮的操作行为封装到ActionChains
ActionChains(driver).move_to_element(setButton)
time.sleep(2)
#在百度文本框中鼠标右键
webEdit = driver.finde_element_by_id("kw")
ActionChains(driver).context_click(webEdit).perform()
time.sleep(5)
driver.quit()
- perform():执行所有ActionChains中存储的行为
-
键盘事件
-
Keys()类提供了键盘上几乎所有的按键的方法
-
send_keys()方法可以用来模拟键盘输入,除此可以用来输入键盘上的按键、组合键
-
导入 from selenium.webdriver.common.keys import keys
-
Send_keys(Keys.Back_SPACE):删除键
-
Send_keys(Keys.SPACE):空格键
-
Send_keys(Keys.TAB):制表键
-
Send_keys(Keys.ESCAPE):esc键
-
Send_keys(Keys.ENTER):回车键
-
Send_keys(Keys.CONTROL,'a'):全选
-
Send_keys(Keys.CONTROL,'c'):复制
-
Send_keys(Keys.CONTROL,'x'):剪切
-
Send_keys(Keys.CONTROL,'v'):粘贴
-
案例:
1.百度”seleniumm“2.删除多输入的m
3.在输入”空格 教程“
4.ctrl+a,全选文本框内容
5.ctrl+x,剪切选择的内容
6.ctrl+v,粘贴复制的内容
7.回车代替单机,完成搜索
8.退出浏览器
#导包、创建浏览器对象、获取一下ur1地址
form selenium import webdriverfrom selenium.webdriver.common.keys import Keys
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")#1.
driver.find_element_by_id("kw").send_keys("seleniumm")
time.sleep(2)
#2.
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
#3.
#再次发送字符串,是和前面的进行拼接
driver.find_element_by_id("kw").send_keys(" 教程")
time.sleep(1)
#4.
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"a")
time.sleep(1)
#5.
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"x")
time.sleep(1)
#6.
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"v")
time.sleep(1)
#7.
driver.find_element_by_id("kw").send_keys(Keys.ENTER)
time.sleep(1)
driver.quit()
-
-
-
-
警告窗口处理
- 模式窗口:只要关闭这个窗口,其他操作一概做不了
- 非模式窗口:不用关闭窗口,也可以进行其他操作
- 在WebDriver中处理JavaScript所生成的
-
警告框-alter,是一个模式窗口
- driver对象是在当前页面窗口内,但是不在alter上,并且我们没办法去定位这个窗口的元素
- driver.switch_to.alter:暂时将浏览器对象driver交给alter用
- 方法定位到alert/confirm/prompt,然后使用
- text:返回(获取)alert/confirm/prompt中的文字信息
- accept():接受现有警告框
- dismiss():放弃现有警告框
- send_keys(keysToSend):发送文本至警告框
-
#导包、创建浏览器对象、获取一下ur1地址
form selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")#将鼠标悬停在设置按钮上
seting = driver.find_element_by_link_text("设置")
ActionChains(driver).move_to_element(seting).perform()
#打开搜索设置按钮
driver.find_element_by_link_text("搜索设置").click()
time.sleep(5)
#点击保存设置
driver.find_element_by_class_name(”prefpanelog“).click()
#弹出警告提示框
time.sleep(5)
driver.switch_to.alter.accept()
time.sleep(5)
#就可以对他操作
dd = driver.switch_to_alert()
#获取alter里面的文本信息
tt = dd.text
#已经记录使用偏好
print(tt)
time.sleep(2)
#接受
dd.accept()
time.sleep(2)
#关闭driver对象
driver.quit()
-
多窗口、多表单处理
- 在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对frame/iframe表单内嵌元素无法识别与定位
-
#导包、创建浏览器对象、打开qq首页
from selenium import webdriver
import time
driver = webdriver.Chrome()
#1.打开腾讯首页
driver.get("https://www.qq.com")
#2.点击邮箱图标
driver.find_element_by_link_text("Qmail").click()
#跳转到邮箱登录页面(窗口),涉及到多窗口的处理
handles = driver.window_handles
#['CDwindow-202C6D7DFFEE1D0432679EF83A62929F', 'CDwindow-6CEF144230FE58CF22922024259570DA']
driver.switch_to.window(handles[1])
#现在先验证窗口跳转是否成功
driver.find_element_by_link_text("基本版").click()
time.sleep(3)
#3.输入用户名
driver.find_element_by_link_text("账号密码登录").click()
driver.find_element_by_xpath('//*[@id="u"]').send_keys("1234567")
time.sleep(2)
#识别不到账号密码登录元素
#涉及到多表单的处理
#第一种方式
#默认可以给ID或name
driver.switch_to.frame("login_frame")#第二种方式
#可以传参iframe的元素对象
iframeObj = driver.find_element_by_xpath('//*[@id="login_frame"]')
driver.switch_to.frame(iframeObj)
#4.输入密码
driver.find_element_by_xpath('//*[@id="p"]').send_keys("abcdefg")
time.sleep(2)
#5.点击登录
driver.find_element_by_xpath('//*[@id="login_button"]').click()
time.sleep(2)
#6.关闭浏览器
driver.quit()
-
设置元素等待
- 隐式等待
- 在脚本创建driver对象后,给driver设置一个全局等待时间,对driver整个生命周期起效
- 若在等待时间(超时时间)内,定位到了页面元素,则不再等待继续执行
- 若超出等待时间,抛出异常
- implicitly_wait()
- 在脚本创建driver对象后,给driver设置一个全局等待时间,对driver整个生命周期起效
- 显式等待
- 明确等到某个元素的出现或某个元素的可点击等条件
- WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
- until(method, info):直到满足某一条件,返回结果,否则就抛异常
- method-->excepted_conditions.presence_of_element_located(locator)
- locator-->By.Id,By.Name
- method-->excepted_conditions.presence_of_element_located(locator)
- 强制等待
- time.sleep():休眠,直接让线程休眠
-
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
#使用隐式等待,直到quit()
driver.implicitly_wait()
driver.get("https://www.baidu.com") #使用显式等待方式等待百度首页的百度一下按钮显示出来
WebDriverWait(driver, 10, 0.5, ele=ignored_exceptions=None).until(EC.presence_of_element_located((By.Id,"kw")),"找不到" )
if ele :
ele.send_keys("selenium")time.sleep(3)
else:
print(ele)
driver.quit()
- 隐式等待
-
-
自动化脚本开发
- 1、自动化测试用例—般可以由手工测试用例转化而来,需注意
- 不是所有的手工测试用例都要转为自动化测试用例
- 考虑到脚本开发的成本,不要选择流程太复杂的用例,可以把流程拆分成多个用例
- 选择的用例最好可以构建成场景
- 选取的用例可以是你认为是重复执行、很耗时间的部分,例如字段验证
- 选取的用例可以是主流程用例,即适用于冒烟测试的用例
- 2、自动化测试用例的设计原则((熟练掌握)
- 一个用例为一个完整的场景,从用户登录系统到最终退出并关闭浏览器
- 一个用例只验证一个功能点,不要试图在用户登录后把所有的功能都验证一遍
- 尽可能少的编写逆向测试用例,一方面因为逆向逻辑的用例很多
- 另一方面自动化测试脚本本身比较脆弱
- 用例和用例之间尽量避免产生依赖。
- —条用例完成测试之后需要对测试场景进行还原,以免影响其它用例的执行
- 3、自动化测试用例设计实践(熟练掌握)
- 测试点转为测试用例的原则是什么?
- 设计一条正向用例。覆盖足够多的有效等价类数据
- 设计一条反向用例,需要覆盖一条无效等价类数据,其他数据一概使用正向数据
- 有验证码的时候,该怎么进行自动化?
- 让开发暂时屏徽验证码、将验证码改为万能码("'aaaa')
- 懂机器学习,可以训练样本,可以达到99%以上识别成功率
- 调用OCR的接口,去解析图片中验证码,然后来用
- 测试点转为测试用例的原则是什么?
- 常见自动化测试模型
- 线性模型:最基本的代码组织形式,模拟用户步骤或者场景
- 1.维护性比较差
- 2.模块比较多,运行起来麻烦。写一个额外的模块作为主运行模块。
- 3.如果所有用力步骤放在一个模块,可读性差
- 模块化驱动测试
- 把常用、公用的一些功能、业务、步骤专门提取出来,写在一个专门的模块中,以方法、类的形式实现出来
- 在其他的模块需要这些功能,直接调用。eg.登录模块、退出模块、邮件发送模块、数据库处理模块、日志生成模块等
- 模块化驱动测试最大程度地去除了重复,提高了测试脚本的复用性和可维护性
-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
def loginVery(driver):
driver.find_element_by_xpath("//"[@id='top-userbar']/a[1]").click()
driver.find_element_by_id("username").send_keys("test1")
driver.find_element_by_id("password").send_keys("123456")
driver.find_element_by_xpath("//*[@id='login-form']/div/a").click()
time.sleep(5)
def logoutVery(driver):
above = driver.find_element_by_xpath("//*[@id='top-userbar']/a")ActionChains(driver).move_to_element(above).perform()
driver.find_element_by_link_text("退出").click()
time.sleep(5)
def quitBrowser(driver):
driver.quit()
if __name__=="__main__":
#创建浏览器对象
driver = webdriver.Chrome()
driver.get("http://47.105.47.131/verydows/")
loginVery(driver)
logoutVery(driver)
quitBrowser(driver)
- 数据驱动测试
- 由数据的改变驱动测试的执行,最终改变测试的结果,就是数据驱动测试
- 数据与业务分离,分离出的数据存储
- 字典
- 数据量小,使用频率高
- 在python定义一个字典类型的数据结构,把数据存进去
- csv文件(excel文件)
- 数据库
- 配置文件
- 字典
- 数据的参数化
- 关键字驱动测试
- 实现类似于模拟selenium IDE工具
- 线性模型:最基本的代码组织形式,模拟用户步骤或者场景
- 1、自动化测试用例—般可以由手工测试用例转化而来,需注意
-
Unittest单元测试框架
- 引入框架
- Web自动化:python+selenium+unittest
- unittest:单元测试框架
- 单元测试:代码级别的功能验证 + 逻辑覆盖
- 单元测试框架
- 提供用例组织与执行
- 提供丰富的断言方法
- 提供丰富的日志和报告(HTML格式更好)
-
#定义一个类,实现加减乘除算法
#对该类中的加减乘除进行单元测试
class mymath():
def jia(self, a, b)
return a+b
def jian(self, a, b):
return a-b
def cheng(self, a, b):
return a*b
def chu(self, a, b):
return a/b
#验证加法
if __name__=="__main__":
mm = mymath()
#实现第一条用例
actualValue == mm.jia(2, 3)
expectValue = 5
if actualValue==expectValue:
print("该加法功能实现正确")
#再来一条用例
#该方法实现正确 can only concatenate str (not "int") to str
try:
actualValue == mm.jia(“a”, 3)
expect Exception as e:
print("该算法实现正确", e)
#需求:设计的方法除数字的运算外,还能进行字符串的拼接
#第三条用例:验证字符串的加法运算
try:
actualValue = mm.jia("a", "b")
expectValue = "ab"
if actualValue==expectValue:
print("该加法功能实现正确")
except Exception as e:
print(e)
- 引入框架unittest、pytest
-
#使用unittest框架设计mymath的单元测试用例 #步骤
1.导包,unittest是自带框架
2.创建一个单元测试类
3.五个特殊方法的使用,包括使用场景及执行顺序
import unittest
#创建一个单元测试类
class unitMymath(unittest, TestCase):
#方法名不能改,self参数不能少
def setUp(self):
print("我是setup方法")
#必须是test开头的方法,测试用例1
def test_add_1(self):
print("我是第一条测试用例")
#方法名不能改,self参数不能少
def tearDown(self):
print("我是teardown方法")
if __name__=='__main__':
#调用执行单元测试类,通过主方法main执行
unnittest.main()
- 引入框架