unittest + HTMLTestRunner

(仅作为个人笔记,如有雷同,请联系删除。。)

nose/nosetests,按照匹配规则收集测试 – [ 先收集,再执行 ]

1、unittest单元测试框架:

(1) 提供用例组织与执行;
(2) 提供丰富的比较方法;
(3) 提供丰富的日志;
# eg:已有一个求和的Count()类
from calculator import Count
import unittest # 导入unittest模块class TestCount(unittest.TestCase): # 继承unittest的TestCase类。(TestCase类:对特定类进行测试的集合)def setUp(self): # setUp()方法用于测试用例执行前的初始化工作print("test start")def test_add(self): # 测试用例j = Count(2, 3)self.assertEqual(j.add(), 5) # assertEqual(),断言,判断两者是否相等def tearDown(self): # tearDown()方法用于测试用例执行之后的善后工作print("test end")if __name__ == '__main__': unittest.main() # unittest提供了全局的main()方法,可方便地将一个单元测试模块变成可直接运行的测试脚本# main()方法使用TestLoader类来搜索所有包含在该模块中以"test"命名开头的测试方法,并自动执行它们

2、关于unittest的4个重要概念:

  1. TestCase:一个TestCase的实例就是一个测试用例。而一个完整的测试用例包括测试前准备环境的搭建(setUp)、实现测试过程的代码(run),以及测试后环境的还原(tearDown)。
  2. TestSuite:一个功能的验证需要多个测试用例,将多个测试用例集合在一起来执行。TestSuite就是用来组装单个测试用例,可以通过addTest方法加载TestCase到TestSuite中,从而返回一个TestSuite实例。
     # 构造测试集:suite = unittest.TestSuite()`suite.addTest(类名("方法名"))
  1. TestRunner:在unittest单元测试框架中,通过TextTestRunner类提供的run()方法来执行TestSuite/TestCase。Testrunner可以使用图形界面、文本界面,或返回一个特殊的值等方式来表示测试结果的执行。
    # 运行测试集:runner = unittest.TextTestRunner()runner.run(suite)
  1. TestFixture:对一个测试用例环境的搭建和销毁,就是一个fixture,通过覆盖TestCase的setUp()和tearDown()方法来实现。
# eg:test.py ---->已有一个求和的Count()类,封装在calculator模块中
from calculator import Count
import unittestclass TestCount(unittest.TestCase):def setUp(self):print("test start")def test_add(self):j = Count(2, 3)self.assertEqual(j.add(), 5)def test_add2(self):j = Count(41, 76)self.assertEqual(j.add(), 117)def tearDown(self):print("test end")if __name__ == '__main__':suite = unittest.TestSuite() # 创建测试集suite.addTest(TestCount("test_add2")) # 将第二个测试用例加载到suite测试集中runner = unittest.TextTestRunner()runner.run(suite) # 运行suite测试集中所组装的测试用例

3、unittest.TestCase类提供的断言方法:

  1. assertEqual(first,second,msg=None):断言第一个参数和第二个参数相等,若不相等则测试失败。msg为可选参数,定意测试失败时打印的信息
  2. assertNotEqual(first,second,msg=None):断言第一个参数和第二个参数不相等,若相等则测试失败
  3. assertTrue(表达式,msg=None):断言表达式结果为True
  4. assertFalse(表达式,msg=None):断言表达式结果为False
  5. assertIn(first,second,msg=None):断言第一个参数在第二个参数中
  6. assertNotIn(first,second,msg=None):断言第一个参数不在第二个参数中
  7. assertIs(first,second,msg=None):断言第一个参数和第二个参数是同一个对象
  8. assertIsNot(first,second,msg=None):断言第一个参数和第二个参数不是同一个对象
  9. assertIsNone(表达式,msg=None):断言表达式为None对象
  10. assertIsNotNone(表达式,msg=None):断言表达式不为None对象
  11. assertIsInstance(obj,cls,msg=None):断言obj是cls的一个实例
  12. assertNotIsInstance(obj,cls,msg=None):断言obj不是cls的实例
# eg:unittest.TestCase类的断言方法.py
import unittestclass Test(unittest.TestCase):def setUp(self):print("test start")def test_case(self):a = "hello"b = "hello world"self.assertIn(a, b, msg="a不在b中!")def tearDown(self):print("test end")if __name__ == "__main__":unittest.main()

4、discover()方法: 由TestLoader类提供,使unittest单元测试框架自动识别测试用例

  1. discover(start_dir, pattern='test*.py', top_level_dir=None):找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到测试用例文件名才能被加载到测试集。如果启动的不是顶层目录,那么顶层目录必须单独指定。
    (1)start_dir:要测试的模块名或测试用例目录
    (2)pattern='test*.py':表示用例文件名的匹配规则。此处匹配文件名以"test"开头的".py"类型的文件,"*"表示任意多个字符
    (3)top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None
#  eg:unittest.TestCase类的断言方法.py
import unittest
class Test(unittest.TestCase):def setUp(self):print("test start")def test_case(self):a = "hello"b = "hello world"self.assertIn(a, b, msg="a不在b中!")def tearDown(self):print("test end")if __name__ == "__main__":unittest.main()

5、unittest执行测试用例的顺序:

默认根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。对于测试目录与测试文件也是一样的加载顺序,只能通过测试用例的命名来提高被执行的优先级。

6、执行多级目录的用例:

   假设有测试目录,对于这样的目录结构,若将discover()方法中的start\_dir参数定义为“./test\_case/”目录,只能加载test\_a.py文件中的测试用例。如果要让unittest框架找到test\_case/的子目录中的测试文件,需要在每个子目录下放一个\_\_init\_\_.py文件。
test_project/test_case/test_bbb/test_ccc/test_c.pytest_b.pytest_ddd/test_d.pytest_a.py

7、跳过测试和预期失败:

unittest提供了如下装饰器:

  1. unittest.skip(reason):无条件的跳过装饰的测试,说明跳过测试的原因
  2. unittest.skipIf(condition, reason):如果条件为真,跳过装饰的测试
  3. unittest.skipUnless(condition, reason):除非条件为真,否则跳过装饰的测试
  4. unittest.expectedFailure():测试标记为失败。不管执行结果是否失败,统一标记为失败
# eg:test.py
import unittest
class MyTest(unittest.TestCase):def setUp(self):passdef tearDown(self):pass@unittest.skip("直接跳过测试")def test_skip(self):print("test_aaa")@unittest.skipIf(3>2, "当条件为True时跳过测试")def test_skip_if(self):print("test_bbb")@unittest.skipUnless(3>2, "除非条件为真,否则跳过测试")def test_skip_unless(self):print("test_ccc")@unittest.expectedFailuredef test_expected_failure(self):assertEqual(2, 3)if __name__ == '__main__':unittest.main()# 注:这些装饰器同样可以作用于测试类,只需将其定义在测试类上面即可。
import unittest@unittest.skip("直接跳过测试该测试类")
class Mytest(unittest.TestCase):......

8、fixtures:

就是使用setUp和tearDown来前后包含测试用例。此外,unittest还提供了对于测试类和模块的fixtures。

  1. setUpModule、tearDownModule:在整个模块的开始与结束时被执行。
  2. setUpClass、tearDownClass:在测试类的开始与结束时被执行,但需要通过@classmethod进行装饰,并且其方法的参数为cls
  3. setUp、tearDown:在测试用例的开始与结束时被执行
# eg:测试用例、测试类和模块的fixtures.py
import unittestdef setUpModule():print("测试模块开始执行 >>>>>>>>>>>>>")def tearDownModule():print("测试模块执行结束 >>>>>>>>>>>>>")class Test(unittest.TestCase):@classmethoddef setUpClass(cls):print("测试类开始执行 ==========>")@classmethoddef tearDownClass(cls):print("测试类执行结束 ==========>")def setUp(self):print("测试用例开始执行 --------------->")def tearDown(self):print("测试用例执行结束 --------------->")def test_case1(self):print("测试用例1")def test_case2(self):print("测试用例2")if __name__ == '__main__':unittest.main()

9、保存测试结果:

写好测试用例文件xxx.py、yyy.py以及测试用例执行文件runtest.py后,首先打开Windows命令提示符,切换到runtest.py所在目录,执行命令:python runtest.py >> report/log.txt 2>&1,(report是与runtest.py同级的目录,其目录下方含有log.txt文件),然后系统自动执行runtest.py文件,会将测试结果保存在report目录下的log.txt文件中,打开…/report/log.txt文件,可查看测试结果。

10、HTMLTestRunner:

unittest单元测试框架的一个扩展,生成易于使用的HTML测试报告。

  1. 下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html,打开网址下载HTMLTestRunner.py文件,下载之后将其放到D:\Python\Lib目录下即可。(注:下载到的是Python2的,需要手动修改为Python3版的,或者直接在网上下载Python3版的即可)

11、使用HTMLTestRunner生成HTTL测试报告:

要注意HTMLTestRunner()和unittest.TextTestRunner()的区别

from HTMLTestRunner import HTMLTestRunner # 导入HTMLTestRunner
......
f = open('./result.html', 'wb') # 以二进制写的形式打开当前目录下的result.html,如果没有,则自动创建该文件
runner = HTMLTestRunner(stream=f, # stream指定测试报告文件title='测试报告标题', # title用于定义测试报告的标题description='测试报告的副标题') # description用于定义测试报告的副标题
runner.run(测试集) # 通过HTMLTestRunner的run()方法运行测试集中所组装的测试用例
f.close() # 关闭测试报告文件# eg:生成HTML测试报告.py
from selenium import webdriver
import unittest
from HTMLTestRunner import HTMLTestRunner
class Baidu_test(unittest.TestCase):def setUp(self):self.driver=webdriver.Firefox()self.driver.implicitly_wait(10)self.base_url="http://www.baidu.com/"def test_baidu_search(self):driver = self.driverdriver.get(self.base_url)driver.find_element_by_id("kw").send_keys("HTMLTestRunner")driver.find_element_by_id("su").click()def tearDown(self):self.driver.quit()if __name__ == "__main__":suite = unittest.TestSuite() #创建测试集suite.addTest(Baidu_test("test_baidu_search")) #向测试集中组装测试用例f = open('./result.html', 'wb') #定义测试报告文件存放路径,创建并打开测试报告文件runner = HTMLTestRunner(stream=f, title='百度搜索测试报告', description='用例执行情况:') #定义测试报告runner.run(suite) #运行测试集中的测试用例f.close() #关闭报告文件

12、生成更易读的测试报告:

为自动化测试用例加上标题——在类或方法的下方,通过三引号(""" “”"或’’’ ‘’’)来添加docstring类型的注释,此注释在平时调用的时候不显示。而HTMLTestRunner可以读取这类注释,显示在测试报告中。

# eg:借用上例:
.......
class Baidu_test(unittest.TestCase):'''百度搜索测试'''.......def test_baidu_search(self):'''搜索关键字:HTMLTestRunner'''......

13、测试报告文件名:

使每次生成的测试报告名称都不重复且有意义,最好的办法是在报告名称中加入当前时间,这样生成的报告既不会重叠,也能更清晰的知道报告的生成时间。
import time :导入time模块

  1. time.time():获取当前时间戳
  2. time.ctime():当前时间的字符串形式
  3. time.localtime():当前时间的struct_time形式
  4. time.strftime:用来获得当前时间,可将时间格式化为字符串。
# eg:继续打开上面的百度搜索测试用例,作如下修改即可:
import time
......
if __name__ == "__main__":......now = time.strftime("%Y-%m-%d %H_%M_%S")filename = './' + now + 'result.html'f = open(filename, 'wb').......

14、项目集成测试报告:使HTMLTestRunner作用于整个测试项目

# eg:runtest.py -------->测试用例执行文件
import unittest,time
from HTMLTestRunner import HTMLTestRunnertest_dir = './test_case'
discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')if __name__ == '__main__':now = time.strftime("%Y-%m-%d %H_%M_%S")filename = test_dir + '/' + now + 'result.html'f = open(filename, 'wb')runner = HTMLTestRunner(stream=f, title='测试报告', description='用例执行情况:')runner.run(discover)f.close()

15、自动发邮件功能:

需要开启POP3/SMTP,并开启客户端授权密码:登录163邮箱–设置–客户端授权密码–开启

# 具体参考:Python笔记,49. 发送邮件
import smtplib # 导入smtplib模块
connect(host,port):# host是指定连接的邮箱服务器,port指定连接服务器的端口号
login(user, password):# user是登录邮箱用户名,password是登录邮箱的密码
sendmail(from_addr,to_addrs,msg):# from_addr是邮件发送者地址,to_addrs是字符串列表,邮件接收者地址,msg是发送的邮件
quit():# 结束SMTP会话# eg:发送HTML格式的邮件.py
import smtplib
from email.mime.text import MIMEText
from email.header import Headersmtpserver = 'smtp.126.com' # 邮箱服务器
user = 'daqiang@126.com' # 发送邮箱的用户名和密码
password = '123456'
sender = 'lixiaojiangde126@126.com' # 发送方邮箱
receiver = '@qq.com' # 接收方邮箱
subject = 'Python发送邮件练习'
msg = MIMEText('<html><h1>你好!</h1></html>', 'utf-8') # 编写HTML类型的邮件正文
msg['Subject'] = Header(subject, 'utf-8') # 添加邮件主题
smtp = smtplib.SMTP() # 创建SMTP对象
smtp.connect(smtpserver) # 连接邮箱服务器
smtp.login(user, password) # 登录邮箱
smtp.sendmail(sender, receiver, msg.as_string()) # 发送邮件
smtp.quit() # 退出

16、查找最新的测试报告:

 测试报告的名称是根据当前时间生成的
# eg:查找最新的测试报告.py
import osresult_dir = 'C:\\Users\Administrator\\Desktop\\Selenium 2练习' # 定义测试报告的目录
lists = os.listdir(result_dir) # 获取目录下的所有文件及文件夹
lists.sort(key=lambda fn: os.path.getmtime(result_dir+'\\'+fn)) # 对目录下的文件及文件夹按时间重新排序
print(('最新的文件为:' + lists[-1]))
file = os.path.join(result_dir, lists[-1]) # 合成文件的路径
print(file)

17、将自动发邮件功能整合到自动化测试项目中:

整个程序的执行步骤可以分为三部分,如下:

  1. 通过unittest框架的discover()找到匹配的测试用例,由HTMLTestRunner的run()方法执行测试用例并生成最新的测试报告文件;
  2. 调用new_report()函数找到测试报告目录下最新生成的测试报告,返回测试报告的路径;
  3. 将得到的最新测试报告的完整路径传给send_mail()函数,实现发送邮件功能。
# eg:runtest.py -------->测试用例执行文件
import unittest,time,os
from HTMLTestRunner import HTMLTestRunner
from email.mime.text import MIMEText
from email.header import Header
import smtplibdef send_mail(file_new): # 定义发送邮件函数f = open(file_new, 'rb'')mail_body = f.read()f.close()msg = MIMEText(mail_body, 'html', 'utf-8')msg['Subject'] = Header("自动化测试报告" ,'utf-8')smtp = smtplib.SMTP()smtp.connect("smtp.126.com")smtp.login("daqiang@126.com", "password")smtp.sendmail("daqiang@126.com", "14xxxxxx28@qq.com", msg.as_string())smtp.quit()print('邮件发送完毕!')def new_report(testreport): # 查找测试报告目录,找到最新生成的测试报告文件lists = os.listdir(testreport)lists.sort(key=lambda fn: os.path.getmtime(testreport + "\\" + fn))file_new = os.path.join(testreport, lists[-1])print(file-new)return file_newif __name__ == '__main__':test_dir = 'D:\\testpro\\test_case'test_report = 'D:\\testpro\\report'discover = unnittest.defautTestLoader.discover(test_dir, pattern='test_*.py')now = time.strftime("%Y-%m-%d %H_%M_%S")filename = test_report + '\\' + now + 'result.html'fp = open(filename, 'wb')runner = HTMLTestRunner(stream=fp, title="自动化测试报告", description="用例执行情况:")runner.run(discover)fp.close()file_new_report = new_report(test_report) # 找到最新生成的测试报告文件send_mail(file_new_report) # 发送测试报告

18、Page Object设计模式:

page对象应当将在GUI控件上的所有查询和操作数据的行为封装为方法。即使改变具体的控件,page对象的接口也不应当发生变化。虽然术语是“页面”对象,但并不意味着需要针对每个页面建立一个这样的对象,例如:页面有重要意义的元素可以独立为一个page对象。· Page Object设计模式 = 页面对象层 + 测试用例

以登录126邮箱为例,通过Page Object设计模式来实现:

  1. 创建Page类:首先创建基础类Page,在初始化方法__init__()中定义驱动(driver)、基本的URL(base_url)和超时时间(timeout)等;
    (1)定义open()方法用于打开URL网站;
    (2)关于URL地址的断言部分,则交由on_page()方法来实现;
    (3)find_element()方法用于元素的定位。
  2. 创建LoginPage类:Page类中定义的方法都是页面操作的基本方法,在此处根据登录页面的特点再创建LoginPage类并继承Page类,这也是Page Object设计模式中最重要的对象层。

LoginPage类中主要对登录页面上的元素进行封装,使其成为更具体的操作方法。例如:用户名、密码、登录按钮都被封装成了方法。

3.创建test_user_login()函数:将单个的元素操作组成一个完整的动作,而这个动作包含了打开浏览器、输入用户名/密码、点击登录按钮等单步操作。在使用该函数时需要将driver、username、password等信息作为函数的入参,这样该函数具有很强的可用性。
4. 创建main()函数:main()函数更接近于用户的操作行为。对于用户来说,要进行邮箱的登录,需要关心的是通过那个浏览器打开邮箱的网址、登录的用户名和密码是什么,至于输入框、按钮是如何定位的,则不需要关心。

注1:这样分层的好处就是,不同的层关心不同的问题。页面对象层只关心元素的定位问题,测试用例只关心测试的数据。注2:关于page对象是否应该自身包含断言,或者仅仅提供数据给测试脚本来设置断言——这是一个有分歧的地方,建议在page对象中不包含断言。

unittest + HTMLTestRunner相关推荐

  1. Selenium UI自动化测试(四)Python+Unittest+HTMLTestRunner测试报告—百度hao123实例

    Python+Unittest+HTMLTestRunner测试报告-百度个人中心实例 环境配置:https://blog.csdn.net/sevensolo/article/details/100 ...

  2. python+requests+unittest+HTMLTestRunner构建接口自动化测试框架(四)测试用例执行

    python+requests+unittest+HTMLTestRunner构建接口自动化测试框架(一)了解基础框架,读取配置文件 python+requests+unittest+HTMLTest ...

  3. 简单案例:unittest+HTMLTestRunner实现生成测试报告

    1 HTMLTestRunner for Mac for installing HTMLTestRunner是标准库拓展脚本,用于实现测试报告生成,和unittest本身的TextTestRunner ...

  4. 单元测试unittest(基于数据驱动的框架:unittest+HTMLTestRunner/BeautifulReport+yaml+ddt)...

    一.定义 unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果 ...

  5. python用unittest+HTMLTestRunner的框架测试并生成测试报告

    直接贴代码: import unittestfrom selenium import webdriverfrom time import sleepimport osimport time # 定义打 ...

  6. Python3 Unittest+HTMLTestRunner.py文件

    1.目录结构 1.test.py 运行主文件 2.req.py 调用requests方法 3.HTMLTestRunner.py这个文件是生成报告的文件,从官网下载,我这里是现成,可能里面需要导入一些 ...

  7. Appium+Unittest+HTMLTestRunner

    雷电模拟器为例: from appium import webdriver import unittest from time import sleep import HTMLTestRunner f ...

  8. py2 HTMLTestRunner报告

    直接上代码吧. 1 #coding:utf-8 2 #__author__ = 'carry' 3 import unittest,HTMLTestRunner 4 5 class Hello(uni ...

  9. python测试用例怎么写_Python单元测试unittest的具体使用示例

    Python中有一个自带的单元测试框架是unittest模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作. unittest是python的标准测试库,相比于其 ...

最新文章

  1. FFmpeg中libswresample库简介及测试代码
  2. linux小窍门──设置时钟和时间
  3. atlas和ajaxpro以及微软企业级类库在一起得web配置文件
  4. java api math_JAVA 函数 Math API
  5. 怎么打开网络访问 计算机共享,电脑只要打开共享提示“无法启用共享访问”如何解决...
  6. sqlparameter多个赋值一行完成_HashMap源码从面试题说起:请一行一行代码描述hashmap put方法...
  7. SpringMVC中获得HttpRequest对象的方法
  8. #define与const定义常量的区别
  9. 滑轮控件研究四、VelocityTracker的简单研究
  10. Django访问静态资源
  11. vmlinuz文件解压方法
  12. Web前端:7大Web开发趋势和技术
  13. Ubuntu CURL下载报错:curl: (77) error setting certificate verify locations:
  14. 文件夹加密狗的加密原理与解密
  15. 标签打印机ESC光栅位图打印指令
  16. FlashFxp配置ftp
  17. 计算机思维--0和1与逻辑
  18. 团队协作软件之confluence和jira的配套使用
  19. 推荐几个好用的网盘搜索引擎
  20. 解决:ADODB.Stream 错误 '800a0bbc' 写入文件失败

热门文章

  1. 穷站长(QIONGZZ.com) - 国内最大的免费空间站,国内最便宜最稳定的空间
  2. hockeyapp 自动收集crash
  3. 基于I.MX6UL平台的WIFI模块AP6214A 驱动移植
  4. 不小心点了计算机一键还原怎么操作,怎么一键还原,详细教您怎样还原电脑系统...
  5. CString 包含头文件
  6. java检测工具_常用Java代码质量检测评估工具
  7. xpath常用的元素定位方式
  8. 《Apple 设计奖 2014》出炉,还无辜的《Threes!》一个公道了
  9. 什么是steam账号红信,如何避免steam账号红信,如何提升选品和消耗速度
  10. jQuery方法返回jQuery对象还是DOM对象