Selenium自动化测试-unittest单元测试框架使用
什么是unittest
这里我们将要用的unittest是python的单元测试框架,它的官网是 https://docs.python.org/2/library/unittest.html,在这里我们可以得到全面的信息。
当我们写的用例越来越多时,我们就需要考虑用例编写的规范与组织,以便于后期的维护,而unittest正是这样一款工具。我们这里用一个示例来展示用unittest脚本是什么样子的
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
#导入unittest包
import unittest, time, re #SearchTest类继承自unittest.TestCase,表明这是一个测试案例
class SearchTest(unittest.TestCase):
#setUp用于初始化工作
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True #以test开头的是我们的测试脚本
def test_search(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("selenium2")
driver.find_element_by_id("su").click() def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True #在每个测试方法后执行,完成清理工作
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors) #整个测试过程集中在unittest的main()模块中,其默认执行以test开头的方法
if __name__ == "__main__":
unittest.main()
通过这个我们大概对unittest有个直观的了解了。unittest.main():使用它可以将一个单元测试模块变为可直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中以“test”命名开头的测试方法,并自动执行。执行方法的默认顺序是:根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以以A开头的测试用例方法会优先执行,以a开头会后执行。
unittest中的概念
TestCase
一个Testcase的实例就是一个测试用例,测试用例就是一个完整的测试流程,包括初始化setUp、运行run、测试后的还原tearDown。unittest.TestCase类,所有测试用例类继承的基本类。此类提供了很多assert方法用于检查比较,部分如下:
多数方法都可以见其名知其意,使用的门槛很低。
TestSuite
对一个功能的测试往往需要多测试用例的,可以把多的测试用例集合在一起执行,这就是TestSuite的概念。常用addTest()方法将一个测试用例添加到测试套件中。
TextTestRunner
是用来执行测试用例的,其中的run(test)用来执行TestSuite/TestCase。测试的结果会保存在TextTestResult实例中。
TestFixture
测试准备前要做的工作和测试执行完后要做的工作.包括setUp()和tearDown()。通过覆盖TestCase的setUp和tearDown来实现。
知道了这几个主要的概念,我们就可以把上面的脚本中的最后一行unittest.main()
,改为以下代码:
#构造测试套件
suite = unittest.TestSuite()
suite.addTest(SearchTest("test_search"))
#执行测试
runner = unittest.TextTestRunner()
runner.run(suite)
执行之后发现和之前用unittest.main()的结果一样。
用例组织
这里我们假设,脚本当中有多个TestCase如test_case1,test_case2…,那我们应该怎样去控制它们的执行顺序呢?
执行测试用例方案一
直接用
unittest.main()
执行,这里它搜索所有以test开头的测试用例方法,按照ASCII的顺序执行多个用例。
执行测试用例方案二
先实例化测试套件,将用例加载进去,再用TextTestRunner去执行用例:
suite=unittest.TestSuite()
suite.addTest(Test('test_case2'))
suite.addTest(Test('test_case1'))
runner=unittest.TextTestRunner()
runner.run(suite)
执行的顺序是用例的加载顺序,比如这里是先执行2后执行1。
执行测试用例方案三
在方案2中,如果我们有成百上千个用例的话,一个一个add进去,是不太现实的,那么我们可以用defaultTestLoader来加载:
test_dir = './'
discover = unittest.defaultTestLoader.discover(test_dir, pattern='*test.py')
runner = unittest.TextTestRunner()
runner.run(discover)
这里用./指定了当前目录,指定了*test.py文件,对其当中的用例进行执行,顺序和方案一相同。
如果这里指定的目录下面有多个经pattern匹配上的.py文件呢?调用discover方法,首先通过test_dir定义查找目录,如果文件名满足定义的pattern,那么我们要用for循环来找出所有被筛选出来的用例,并将其循环加到套件中,主要代码如下:
for test_suite in discover:
for test_case in test_suite:
test_unit.addTests(test_case)
由上面组织用例的方式我们可以知道,在实际的测试用脚本开发中,我们可以在目录下创建xx.py的文件,当用例稳定运行后,可以修改成test_xx.py,以便于添加到测试套件中。注意,文件名的匹配规则,我们可以随便由pattern参数定义。
如果要执行多级目录结构的用例呢?要想被discover读取执行,我们要在目录下加_ init _.py文件
一个例子
下面简单的介绍一个用unittest组织的用例结构,先建立D:\Test_Project目录,下面放上test_case和test_report来分别存放用例和报告。
编写测试用例
在test_case下面编写用例,如下简单的示范了在百度上搜索关键字和点击设置的操作:
文件名为:test_baidu.py # -*- coding: utf-8 -*-
from selenium import webdriver
import unittest, time, re class MyTest(unittest.TestCase): def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.baidu.com"
self.accept_next_alert = True def test_02baidu_search(self):
u''' 测试百度搜索'''
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("selenium-test")
driver.find_element_by_id("su").click()
print("test_baidu__test_02baidu_search") def test_01baidu_setting(self):
u''' 测试百度首页设置 '''
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_css_selector("div#u1 a.pf").click()
driver.find_element_by_class_name("setpref").click()
driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
driver.switch_to_alert().accept()
print("test_baidu__test_01baidu_setting") def tearDown(self):
self.driver.close() #从all_test中调用时,可以不要这个
if __name__ == "__main__":
unittest.main()
为了显示出组织测试用例的效果,我们将此文件再复制一份,把文件名和方法名等修改一下:
文件名为:test_baidu2.py # -*- coding: utf-8 -*-
from selenium import webdriver
import unittest, time, re class MyTest(unittest.TestCase):
u''' 测试baidu的第二个用例'''
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.baidu.com"
self.accept_next_alert = True def test_02baidu_search(self):
u''' 测试baidu的第二个用例的test_02baidu_search'''
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").click()
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("selenium-test")
driver.find_element_by_id("su").click()
print("test_baidu2__test_02baidu_search") def test_01baidu_setting(self):
u''' 测试baidu的第二个用例的test_01baidu_setting'''
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_css_selector("div#u1 a.pf").click()
driver.find_element_by_class_name("setpref").click() driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
driver.switch_to_alert().accept()
print("test_baidu2__test_01baidu_setting") def tearDown(self):
self.driver.close() if __name__ == "__main__":
unittest.main()
美化报告样式和发送结果邮件
上面我们写了 两个测试用例作为示例,我们也可以添加更多的进去。接着我们使用HTMLTestRunner这个开源模块来美化测试报告,关于它的下载使用可以参考https://pypi.python.org/pypi/HTMLTestRunner。然后,我们可以在代码中写上运行完成之后自动发送测试邮件出来,便于我们查看。请参看以下代码:
#coding=utf-8
import unittest
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
import HTMLTestRunner
from email.mime.application import MIMEApplication #---发送邮件---
def send_email(report_file):
sender = "XXXXXX@qq.com"
receiver = "XXXXXX@qq.com"
smtpserver = "smtp.qq.com"
#发送邮箱的账号密码,此处使用的是qq邮箱和第三方登录的授权码
username = "XXXXXX@qq.com"
password = "gfomcomojtuudijc" #定义邮件正文
file = open(report_file,"rb")
mail_body = file.read()
file.close() msg = MIMEText(mail_body, _subtype="html", _charset="utf-8")
msg["Subject"] = u"自动化测试报告" smtp = smtplib.SMTP_SSL("smtp.qq.com")
smtp.login(username, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()
print("Email has send out !") #---将用例添加到测试套件---
def creatsuite():
testunit=unittest.TestSuite()
test_dir = "D:\\Test_Project\\test_case"
discover = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py",
top_level_dir = None)
for test_suite in discover:
for test_case in test_suite:
testunit.addTest(test_case)
print (testunit)
return testunit if __name__ == "__main__":
current_time = time.strftime("%Y-%m-%d-%H-%M")
report_dir = "D:\\Test_Project\\test_report\\"
report_file = report_dir + current_time + "-Test_Result.html"
report_stream = open(report_file, "wb")
# runner = unittest.TextTestRunner()
# 注意HTMLTestRunner只支持python2
runner = HTMLTestRunner.HTMLTestRunner(stream=report_stream,title=u"自动化测试报告", description=u"用例执行情况如下:")
runner.run(creatsuite())
report_stream.close()
send_email(report_file)
在上面的代码中我们使用了runner = HTMLTestRunner.HTMLTestRunner()
方法来代替runner = unittest.TextTestRunner()
,是为了使用HTMLTestRunner这个模块来美化和输出美观的报告。然后调用方法来发送邮件。运行此文件后,可以得到以下输出的报告:
可以看见使用这个可以清晰的看到用例的执行情况, 也便于查看失败用例的原因去调试它,同时在们输入的收件箱也会收到一份通知邮件,我们可以将此输出报告添加到正文或附件中,以便于查看
Selenium自动化测试-unittest单元测试框架使用的更多相关文章
- Selenium自动化测试-unittest单元测试框架
一.Pyhon工作原理-- 核心概念:test case, testsuite, TestLoder,TextTestRunner,TextTestResult, test fixture TestC ...
- Selenium 2自动化测试实战26(unittest单元测试框架)
一.unittest单元测试框架 1.认识单元测试 1.断言方法 #计算器类 #coding:utf-8 #计算器类 class Count: def __init__(self,a,b): self ...
- Selenium+Python ---- 免登录、等待、unittest单元测试框架、PO模型
1.免登录在进行测试的过程中难免会遇到登录的情况,给测试工作添加了工作量,本文仅提供一些思路供参考解决方式:手动请求中添加cookies.火狐的profile文件记录信息实现.人工介入.万能验证码.去 ...
- Python+Selenium框架设计篇之-简单介绍unittest单元测试框架
前面文章已经简单介绍了一些关于自动化测试框架的介绍,知道了什么是自动化测试框架,主要有哪些特点,基本组成部分等.在继续介绍框架设计之前,我们先来学习一个工具,叫unittest. unit ...
- Selenium基于Python web自动化基础二 -- 免登录、等待及unittest单元测试框架
一.免登录在进行测试的过程中难免会遇到登录的情况,给测试工作添加了工作量,本文仅提供一些思路供参考解决方式:手动请求中添加cookies.火狐的profile文件记录信息实现.人工介入.万能验证码.去 ...
- Selenium(十八):unittest单元测试框架(四) HTML测试报告
1. HTML测试报告 对测试人员来而言,测试的产出很难衡量.换句话说,测试人员的价值比较难以量化和评估,相信这一点对软件测试人员来说深有体会.我们花费了很多时间与精力所做的自动化测试也是如此.所以, ...
- Selenium(十七):unittest单元测试框架(三) 脚本分析、编写Web用例
1. 带unittest的脚本分析 也许你现在心里还有疑问,unittest框架与我们前面所编写的Web自动化测试之间有什么必然联系吗?当然有,既然unittest可以组织.运行测试用例,那么为什么不 ...
- 华为五年自动化测试工程详细解说:unittest单元测试框架
一.单元测试框架说明 单元测试是指在编程中,针对程序模块的最小单元(类中的方法)进行正确性检验的测试工作.python+selenium自动化测试中通常使用unittest或者pytest作为单元 ...
- Python+selenium之简单介绍unittest单元测试框架
Python+selenium之简单介绍unittest单元测试框架 一.unittest简单介绍 unittest支持测试自动化,共享测试用例中的初始化和关闭退出代码,在unittest中最小单元是 ...
随机推荐
- 死磕 java集合之TreeMap源码分析(一)- 内含红黑树分析全过程
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 TreeMap使用红黑树存储元素,可以保证元素按key值的大小进行遍历. 继承体系 Tr ...
- 【JMeter】(2)---HTTP压测
JMeter---HTTP压测 一.创建线程组 右击-->添加-->Threads(Users)-->线程组 下面对比较重要的几个参数,讲解下: 名称: 就是给你这个线程组起名字. ...
- 使用Phalcon框架开发一个简易的博客系统
使用Phalcon PHP框架开发一个简易的博客系统(类似于CMS) 最近在做Phalcon(Phalcon在英文中指的是鸟类中飞得最快的那一个物种,由于是高性能框架,借用了这个词)相关的项目,由于刚 ...
- 程序员过关斩将--面试官再问你Http请求过程,怼回去!
菜菜哥,X总在产品部瞎指挥,作为程序媛的我都快撑不住了 不光你撑不住了,大家都要撑不住了,外行人指导内行人,呵呵 前天我偷偷的去面试了,结果挂了 出去转转其实是好事,面试官问你什么了? 他让我描述一个 ...
- python学习第三讲,python基础语法之注释,算数运算符,变量.
目录 python学习第三讲,python基础语法之注释,算数运算符,变量. 一丶python中的基础语法,注释,算数运算符,变量 1.python中的注释 2.python中的运算符. 3.pyth ...
- MaxCompute/DataWorks权限问题排查建议
MaxCompute/DataWorks权限问题排查建议 __前提:__MaxCompute与DataWorks为两个产品,在权限体系上既有交集又要一定的差别.在权限问题之前需了解两个产品独特的权限体 ...
- NTP服务器搭建
NTP服务器搭建 :http://www.jbxue.com/LINUXjishu/22352.html 客户端配置: vim /etc/ntp.conf #server 0.centos.pool. ...
- Oracle学习笔记三
一.创建表空间 表空间是ORACLE数据库的逻辑单元.数据库--表空间 一个表空间可以与多个数据文件(物理结构)关联一个数据库下可以建立多个表空间,一个表空间可以建立多个用户个用户下可以建立多个表. ...
- Java多线程概念简介 多线程中篇(一)
Java的线程与操作系统的线程 在线程的相关介绍中,有讲到“线程的实现”分为三种:内核支持,用户级以及两者混合.(这只是一种简要的分类) Java线程在JDK1.2之前,是用户线程实现的 而在JD ...
- VisualStudio移动开发(C#、VB.NET)Smobiler开发平台——BarcodeView控件的使用方式,.Net移动开发
BarcodeView控件 一. 样式一 我们要实现上图中的效果,需要如下的操作: 从工具栏上的“Smobiler Components”拖动一个BarcodeView控件到窗体界面 ...