python unittest单元测试

版权声明:本文为CSDN博主「药药君」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Static_at/article/details/82840337

基础

unittest是python自带的一个测试框架,也称单元测试。

使用时必须导入unittest模块。

#coding:utf-8
import unittest
class MathTestCase(unittest.TestCase):#定义一个类,继承unittest.TestCase
    def testSub(self): ## test method names begin 'test*' 告诉我们写函数时要以test开头
        self.assertEqual(2-1,1)   #assertEqual表示断言,2-1的预期结果是1
        self.assertEqual((3-3),0)
 
    def testDiv(self):
        self.assertEqual(2/1,2)
        self.assertEqual((3/2),1.5)
if __name__=="__main__":
    unittest.main()
 

运行结果:
在这里插入图片描述
总结:

1.单元测试需要导入包 import unittest

2.类必须继承unittest.testCase

3.构建的函数必须以test关键字开头

4.运行所有函数使用 unittest.main()

5.断言使用 self.assertEqual()

setUp()和tearDown()应用

setUp:表示前置条件,它在每一个用例执行之前必须会执行一次

setUp可以理解为我们需要自动化测试时,需要打开网页窗口,输入对应测试地址,这一些属于前置条件。

tearDown:表示释放资源,它在每次用例执行完之后会执行一次

tearDown可以理解为我们测试完毕后,需要关闭浏览器。

以下示例演示setUp和tearDown的执行顺序:

#coding:utf-8
from selenium import webdriver
import unittest
from time import sleep
class Baidu_search(unittest.TestCase):
    def setUp(self):
        self.bro=webdriver.Firefox()
        self.bro.maximize_window()
        self.bro.get("https://www.baidu.com")
        sleep(1)
    def tearDown(self):
        sleep(1)
        self.bro.quit()
    def test_search2(self):  #代码运行顺序和函数名相关
        self.bro.find_element_by_id("kw").send_keys(u"第二次单元测试")
        self.bro.find_element_by_id("su").click()
        sleep(1)
 
    def test_search1(self):
        self.bro.find_element_by_id("kw").send_keys(u"第一次单元测试")
        self.bro.find_element_by_id("su").click()
        sleep(1)
 
if __name__=="__main__":
    unittest.main()

跳过执行某个测试用例的方法

概括

@unittest.skip(reason):强制跳转。reason是跳转原因
@unittest.skipIf(condition, reason):condition为True的时候跳转
@unittest.skipUnless(condition, reason):condition为False的时候跳转
@unittest.expectedFailure:如果test失败了,这个test不计入失败的case数目
 self.skipTest(reason):一般写在函数体内部

代码示例(以bilibili登录为例)

from selenium import webdriver
import unittest
from time import sleep


class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://passport.bilibili.com/login')
        sleep(2)

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

    def testLogin01(self):
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('autotest')  #注意修改账号密码
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('123456')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()



    @unittest.skip('用户名密码都为空,测试用例不执行')
    def testLogin02(self):
        username = self.driver.find_element_by_xpath("//input[@id='login-username']").text
        password = self.driver.find_element_by_xpath("//input[@id='login-passwd']").text
        self.assertEqual(username, '用户名不为空')
        self.assertEqual(password, '密码不为空')
    #
    @unittest.skipIf(3 > 2, '3大于2,测试用例不执行')
    def testLogin03(self):
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('autotest')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('123456')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()
        sleep(2)
        self.driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
        sleep(2)
        co = self.driver.find_element_by_xpath("//div[@class='text-con']/p/span[2]").text
        self.assertEqual(co, '网络文化经营许可证 沪网文【2019】3804-274号')
    #
    """
    这个用例不进行注释,其他test代码就不会执行,会直接执行这个
    @unittest.skipUnless(3<2, '2>3不执行测试用例')
    # @unittest.expectedFailure
    def testLogin04(self):
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('autotest')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('123123')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()
        err_info = self.driver.find_element_by_xpath("//div/p[text()='账号或密码错误']").text
        self.assertEqual(err_info, '账号或密码错误')"""

    def testLogin05(self):
        self.skipTest('通过skipTest跳过这个测试用例')
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('autotest')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('123456')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()


if __name__ == '__main__':
    unittest.main()
1. @unittest.skipUnless()装饰器和其他代码一起运行时,其他test代码不执行

在这里插入图片描述

2. @unittest.skipUnless()内容注释后

在这里插入图片描述

批量运行测试用例

test01的代码:

#coding:utf-8
class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://passport.bilibili.com/login')
        sleep(2)

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

    def testLogin01(self):
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('15755189711')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('2bqingnian')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()



    @unittest.skip('用户名密码都为空,测试用例不执行')
    def testLogin02(self):
        username = self.driver.find_element_by_xpath("//input[@id='login-username']").text
        password = self.driver.find_element_by_xpath("//input[@id='login-passwd']").text
        self.assertEqual(username, '用户名不为空')
        self.assertEqual(password, '密码不为空')
    #
    @unittest.skipIf(3 > 2, '3大于2,测试用例不执行')
    def testLogin03(self):
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('15755189711')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('2bqingnian')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()
        sleep(2)
        self.driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
        sleep(2)
        co = self.driver.find_element_by_xpath("//div[@class='text-con']/p/span[2]").text
        self.assertEqual(co, '网络文化经营许可证 沪网文【2019】3804-274号')
    # @unittest.skipUnless(3<2, '2>3不执行测试用例')
    # # @unittest.expectedFailure
    # def testLogin04(self):
    #     self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('15755189711')
    #     self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('2fyuqsdttgna')
    #     self.driver.find_element_by_xpath("//a[text()='登录']").click()
    #     err_info = self.driver.find_element_by_xpath("//div/p[text()='账号或密码错误']").text
    #     self.assertEqual(err_info, '账号或密码错误')

    def testLogin05(self):
        self.skipTest('通过skipTest跳过这个测试用例')
        self.driver.find_element_by_xpath("//input[@id='login-username']").send_keys('15755189711')
        self.driver.find_element_by_xpath("//input[@id='login-passwd']").send_keys('2bqingnina')
        self.driver.find_element_by_xpath("//a[text()='登录']").click()


if __name__ == '__main__':
    unittest.main()

在单元测试中批量运行测试用例的方法有两种。

第一种是通过手动添加,通过unittest.Testsuite来管理用例集,通过addTest添加用例方法,再通过实例化TextTestrunner运行测试。

第二种是通过自动识别用例的目录对所有的用例进行运行。使用到discover()函数。

首先来演示第一种手动添加写法:创建一个test_air.py

#coding:utf-8
import unittest
from baidu_search import Baidu_search
class Xseq(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print "前置测试条件"
    @classmethod
    def tearDownClass(cls):
        print "结束测试条件"
    def testadd(self):
        print '1+1=',1+1
    def testsub2(self):
        print '3-2=',3-2
    def testsub1(self):
        print '3-3=',3-3
if __name__=="__main__":
    suite = unittest.TestSuite() #实例化用例集
    suite.addTest(Xseq("testsub1")) #把testsub1测试用例添加到用例集
    suite.addTest(Xseq("testsub2"))
    #suite.addTest(Baidu_search("test_search2"))
    runner = unittest.TextTestRunner() #实例化运行类
    runner.run(suite) #运行用例集,会根据添加的用例顺序进行用例的执行
 
    # unittest.main()#运行所有函数
总结:

实例化用例集: 用例集对象名 = unittest.TestSuite()
添加用例到用力集写法: 用例集对象名.addTest(类名(“函数名”))
实例化运行类: 运行对象名 = unittest.TextTestRunner()
运行用例集: 运行对象名.run(用例集对象名)

在有很多用例需要运行的时候,不可能一个个用例手动过去添加。

或是用例函数方法名改变之后,也不可能每一个添加用例的地方都要去修改,这里就需要用到第二个方法,通过路径去识别用例,从而去实现执行用例的方法。

第二种自动识别路径去运行的方法演示:

import unittest
import os

def allrun():
    test_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)))#获取当前工作目录
    # test_dir = os.path.join(os.path.dirname(os.path.realpath('E:\project\untitled\test_devlopment')))#获取当前工作目录
    #用discover的方法去覆盖所有的测试用例
    # test_dir 要执行的测试用例目录
    # test*表示匹配以test开头的所有.py文件
    # top_level_dir=None 测试模块的顶级目录,没有的话就写None
    discover = unittest.defaultTestLoader.discover(test_dir,pattern="test*.py",top_level_dir=None)
    runner = unittest.TextTestRunner() #实例化runner类
    runner.run(discover) #执行路径中匹配的所有test*.py用例
allrun()

在这里插入图片描述
运行结果:
在这里插入图片描述

总结:

在获取系统目录时需要加入os模块,os模块是对系统操作时必须存在的。当前目录使用过的os方法请前往python os模块

导入os模块: import os

获取当前工作目录: 目录对象名 = os.path.join(os.path.dirname(os.path.realpath(file)))

用discover()函数覆盖测试用例方法:

用例集对象名 = unittest.defaultTestLoader.discover(目录对象名,pattern=“test*.py”,top_level_dir=None)

实例化运行类 : 运行对象名 = unittest.TextTestRunner()

执行所有匹配的测试用例: 运行对象名.run(用例集对象名)

封装discover加载测试用例方法

把用例和这个封装的方法都放在一个工作目录下。

封装一个discover方法可以直接在这个方法写执行所有匹配的测试用例。

#coding:utf-8
import unittest
import os
 
def Run_all_test():
    #实例化覆盖对象,匹配test*.py的文件
    case_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)))  # 获取当前工作目录(用例也放在该目录下)
    discover = unittest.defaultTestLoader.discover(case_dir,"test*.py",top_level_dir=None)
    return discover #返回实例化对象(用例集)
 
if __name__=="__main__":
    runner = unittest.TextTestRunner() #实例化运行类
    runner.run(Run_all_test()) #执行所有的匹配用例集

生成测试报告并发送到邮件

unittest单元测试不支持直接生成测试报告,因此测试报告都是通过第三方模块来进行导出。

而第三方库导出的测试报告呈现以HTML形式,而第三方模块名称为 HTMLTestRunner

下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

1.图下选择红框里的HTMLTestRunner.py,打开后把网页另存为即可下载。

2.下载好后把HTMLTestRunner.py放到python的Lib目录下即可
在这里插入图片描述

在使用的时候导入HTMLTestRunner包即可。

以下为代码演示(其中封装好的发送邮件模块,请点击Send_email查阅)

#coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8') #以上三行是python2.x版本需要加入,不然会报错
from selenium import webdriver
import unittest
import os
from HTMLTestRunner import HTMLTestRunner
from time import sleep
from Send_email import send_email  #导入已封装好的发送邮件模块
class Baidu_search(unittest.TestCase):
    def setUp(self):
        self.bro = webdriver.Chrome()
        self.bro.maximize_window()
        self.bro.get("https://www.baidu.com")
        sleep(1)
    def tearDown(self):
        sleep(1)
        self.bro.quit()
    def test_search2(self):
        self.bro.find_element_by_id("kw").send_keys(u"第二次单元测试")
        self.bro.find_element_by_id("su").click()
        sleep(1)
    def test_search1(self):
        self.bro.find_element_by_id("kw").send_keys(u"第一次单元测试")
        self.bro.find_element_by_id("su").click()
        sleep(1)
if __name__ == "__main__":
    # 获取当前工作目录:
    test_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)))
    #默认加载覆盖当前目录下的test匹配的测试用例:
    discover = unittest.defaultTestLoader.discover(test_dir,pattern="test*.py",top_level_dir=None)
    #测试报告保存路径:保存在当前目录,以result.hmtl为名保存,该名可以随意取
    test_report = os.path.join(os.path.dirname(os.path.realpath(__file__)),"result.html")
    #通过打开文件流,以二进制的格式写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件:
    fp = open(test_report,"wb")
    #实例化测试报告对象,其中有三个参数,stream表示文件流,title表示测试报告标题,description表示测试报告描述:
    runner = HTMLTestRunner(stream=fp,title=u"我是测试报告标题",description="我是测试报告描述")
    runner.run(discover)    #执行测试用例
    fp.close() #关闭数据流才会生成测试报告
    send_email() #发送测试报告到指定邮件

总结:

  1. 使用HTMLTestRunner必须导入包:from HTMLTestRunner import HTMLTestRunner

  2. 测试报告保存路径写法: 测试报告文件名 = os.path.join(os.path.dirname(os.path.realpath(file)),“result.html”)

  3. 打开文件流,写入报告: fp = open(测试报告文件名,“wb”)

  4. 实例化测试报告对象: 测试报告对象名 = HTMLTestRunner(steam=fp,title=“测试的报告标题”,description=“测试的报告描述”)

  5. 关闭文件数据流: fp.close()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值