码迷,mamicode.com
首页 > 其他好文 > 详细

单元测试框架unittest

时间:2020-11-10 11:04:54      阅读:5      评论:0      收藏:0      [点我收藏+]

标签:验证   odi   断言   rdo   python3   测试框架   cli   bsp   重构   

1、什么是单元测试

  测试函数/方法或者一段代码,用于检验被测代码的一个很小的、很明确的功能是否正确,通常是开发做。

2、单元测试框架

1)结构

测试基本setup方法:第一个测试开始之前只执行一次
多个类
类:
    类setup方法:在当前类的第一个测试方法调用前执行,只执行一次

        setup方法:在执行测试方法前的一些环境或者数据相关的准备
        测试的方法:每个测试方法执行前,都会执行setup方法,然后执行teardown方法
        teardown方法:在执行方法后的一些环境或者数据相关的清理

    类teardown方法:在当前类的最后一个测试方法调用后执行,只执行一次

测试级别teardown方法:所有的测试结束之后只执行一次

2)说明

  setUp:实现测试前的初始化工作

  tearDown:实现测试结束后的清理工作

  集合所有的测试用例并将测试结果独立地战士在测试架构中。

3)Unittest框架的四个概念

  test fixtures:测试固件

  test case:测试用例

  test suit:测试套件

  test runner:测试运行器

4)单元测试的两种加赠方法:

  方法1:unittest.main() 方法加载单元测试的测试模块,执行顺序按照方法名的ascii码升序排序

  方法2:将所有的test case 添加到Test Suite 集合中,然后一次性加载所有测试对象

 

3、代码举例

举例1:

#encoding=utf-8
import unittest

# 被测试类
class myclass(object):
    @classmethod #可以不加,但是调用前需要实例化
    def sum(self, a, b):
        return a + b #将两个传入参数进行相加操作

    @classmethod #可以不加,但是调用前需要实例化
    def sub(self, a, b):
        return a - b #将两个传入参数进行相减操作


class mytest(unittest.TestCase):
    @classmethod #必须加
    def setUpClass(cls):#每个测试类的setup方法,只会执行一次
        "初始化类固件,固件是准备的意思"
        print ( "----setUpClass")

    @classmethod #必须加
    def tearDownClass(cls):#每个测试类的tearDown方法,只会执行一次
        "重构类固件"
        print ( "----tearDownClass")

    # 初始化工作
    def setUp(self):#每个测试方法均会执行一次
        self.a = 3
        self.b = 1
        print ( "--setUp")

    # 退出清理工作
    def tearDown(self):#每个测试方法均会执行一次
        print ( "--tearDown")

    # 具体的测试用例,一定要以test开头
    def testsum(self): #每个测试用例执行成功一次,打印一个 .
        # 断言两数之和的结果是否是4
        self.assertEqual(myclass.sum(self.a, self.b), 4, test sum fail)

    def testsub(self):
        # 断言两数之差的结果是否是2
        self.assertEqual(myclass.sub(self.a, self.b), 2, test sub fail)


if __name__ == __main__:
    unittest.main() # 启动单元测试

执行结果:

技术图片

 

举例2:跳过指定的测试用例的三种方法

# coding=utf-8
import random
import unittest    
import sys

class TestSequenceFunctions(unittest.TestCase):
    a = 6

    def setUp(self):
        self.seq = list(range(10))

    @unittest.skip("skipping") # 无条件忽略该测试方法
    def test_shuffle(self):
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, list(range(10)))
        self.assertRaises(TypeError, random.shuffle, (1, 2, 3))

    # 如果变量a > 5,则忽略该测试方法
    @unittest.skipIf(a > 5, "condition is not satisfied!")
    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    # 除非执行测试用例的平台是Linux平台,否则忽略该测试方法  win32是windows
    @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") #被忽略时打印 第二个参数
    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)


if __name__ == __main__:
    # unittest.main()
    # 指定加载哪几个测试类,生成测试集合
    suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
    suite = unittest.TestSuite(suite)
    unittest.TextTestRunner(verbosity = 2).run(suite)

结果:

D:\学习\自动化\单元测试>py -3 e4_unittest_skip.py
test_choice (__main__.TestSequenceFunctions) ... skipped condition is not satisfied!
test_sample (__main__.TestSequenceFunctions) ... skipped requires Linux
test_shuffle (__main__.TestSequenceFunctions) ... skipped skipping

----------------------------------------------------------------------
Ran 3 tests in 0.003s

OK (skipped=3)

 

举例3:常用断言举例

#encoding=utf-8
import unittest
import random

# 被测试类
class MyClass(object):
    @classmethod
    def sum(self, a, b):
        return a + b

    @classmethod
    def div(self, a, b):
        return a / b

    @classmethod
    def retrun_None(self):
        return None

# 单元测试类
class MyTest(unittest.TestCase):

    # assertEqual()方法实例
    def test_assertEqual(self):
        # 断言两数之和的结果
        # 一般不需要捕获异常,unittest会自动捕获异常
        try:
            a, b = 1, 2
            sum = 3
            self.assertEqual(a + b, sum, 断言失败,%s + %s != %s %(a, b, sum))
        except AssertionError as e:
            print (e)

    # assertNotEqual()方法实例
    def test_assertNotEqual(self):
        # 断言两数之差的结果
        try:
            a, b = 5, 2
            res = 1
            self.assertNotEqual(a - b, res, 断言失败,%s - %s != %s %(a, b, res))
        except AssertionError as e:
            print (e)

    # assertTrue()方法实例
    def test_assertTrue(self):
        # 断言表达式的为真
        try:
            self.assertTrue(1 == 1, "表达式为假")
        except AssertionError as e:
            print (e)

    # assertFalse()方法实例
    def test_assertFalse(self):
        # 断言表达式为假
        try:
            self.assertFalse(3 == 2, "表达式为真")
        except AssertionError as e:
            print (e)

    # assertIs()方法实例
    def test_assertIs(self):
        # 断言两变量类型属于同一对象
        try:
            a = 12
            b = a
            self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
        except AssertionError as e:
            print (e)

    # test_assertIsNot()方法实例
    def test_assertIsNot(self):
        # 断言两变量类型不属于同一对象
        try:
            a = 12
            b = "test"
            self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
        except AssertionError as e:
            print (e)

    # assertIsNone()方法实例
    def test_assertIsNone(self):
        # 断言表达式结果为None
        try:
            result = MyClass.retrun_None()
            self.assertIsNone(result, "not is None")
        except AssertionError as e:
            print (e)

    # assertIsNotNone()方法实例
    def test_assertIsNotNone(self):
        # 断言表达式结果不为None
        try:
            result = MyClass.sum(2, 5)
            self.assertIsNotNone(result, "is None")
        except AssertionError as e:
            print (e)

    # assertIn()方法实例
    def test_assertIn(self):
        # 断言对象A是否包含在对象B中
        try:
            strA = "this is a test"
            strB = "is"
            self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
        except AssertionError as e:
            print (e)

    # assertNotIn()方法实例
    def test_assertNotIn(self):
        # 断言对象A不包含在对象B中
        try:
            strA = "this is a test"
            strB = "Selenium"
            self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
        except AssertionError as e:
            print (e)

    # assertIsInstance()方法实例
    def test_assertIsInstance(self):
        # 测试对象A的类型是否值指定的类型
        try:
            x = MyClass
            y = object
            self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
        except AssertionError as e:
            print (e)

    # assertNotIsInstance()方法实例
    def test_assertNotIsInstance(self):
        # 测试对象A的类型不是指定的类型
        try:
            a = 123
            b = str
            self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
        except AssertionError as e:
            print (e)

    # assertRaises()方法实例
    def test_assertRaises(self):
        # 测试抛出的指定的异常类型
        # assertRaises(exception)
        with self.assertRaises(TypeError) as cm:
            random.sample([1,2,3,4,5], "j")
        # 打印详细的异常信息
        #print "===", cm.exception

        # assertRaises(exception, callable, *args, **kwds)
        try:
            self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
        except ZeroDivisionError as e:
            print (e)

    # assertRaisesRegexp()方法实例
    def test_assertRaisesRegexp(self):
        # 测试抛出的指定异常类型,并用正则表达式具体验证
        # assertRaisesRegexp(exception, regexp)
        with  self.assertRaisesRegex(ValueError, literal) as ar:
            int("xyz")
        # 打印详细的异常信息
        #print ar.exception
        # 打印正则表达式
        #print "re:",ar.expected_regexp

        # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
        try:
            self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ‘$", int, XYZ)
        except AssertionError as e:
            print (e)


if __name__ == __main__:
    # 执行单元测试
    unittest.main()

 

举例4:生成图形化测试报告

导入文件HTMLTestRunner.py ;放到python的安装目录下(D:\Python37-32\Lib\site-packages)

运行对应的主方法:

import unittest

import HTMLTestRunner

if __name__ == __main__ :
    # 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
    testSuite = unittest.TestLoader().discover(.)
    filename = "test.html"  # 定义个报告存放路径,支持相对路径。
    # 以二进制方式打开文件,准备写
    fp = open(filename, wb)
    # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
    runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
        title = Report_title, description = Report_description)
    # 运行测试集合
    runner.run(testSuite)

结果:

技术图片

 举例5:单元测试框架跑UI测试

#encoding=utf-8
import unittest
from selenium import webdriver
import time

class GloryRoad(unittest.TestCase):
    def setUp(self):
        # 启动Chrome浏览器
        # 驱动文件位置要改,本地自己的驱动
        self.driver = webdriver.Chrome()

    def testSoGou(self):
        # 访问搜狗首页
        self.driver.get("http://sogou.com")
        # 清空搜索输入框默认内容
        self.driver.find_element_by_id("query").clear()
        # 在搜索输入框中输入“光荣之路自动化测试”
        self.driver.find_element_by_id("query").send_keys(u"WebDriver实战宝典")
        # 单击“搜索”按钮
        self.driver.find_element_by_id("stb").click()
        # 等待3秒
        time.sleep(3)
        assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")


    def testBing(self):
        # 访问bing首页
        self.driver.get("http://cn.bing.com")
        # 清空搜索输入框默认内容
        self.driver.find_element_by_id("sb_form_q").clear()
        # 在搜索输入框中输入“光荣之路自动化测试”
        self.driver.find_element_by_id("sb_form_q").send_keys(u"WebDriver实战宝典")
        # 单击“搜索”按钮
        self.driver.find_element_by_id("sb_form_go").click()
        # 等待3秒
        time.sleep(3)
        assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")


    def tearDown(self):
        # 退出浏览器
        self.driver.quit()

if __name__ == __main__:
    unittest.main()

 

 举例6:单元测试和ddt数据驱动结合

安装包:pip3 install ddt

代码:

import unittest
import ddt


@ddt.ddt
class Praddt(unittest.TestCase):

    def setUp(self):
        print("my test start!")

    def tearDown(self):
        print("my test complete!")

    @ddt.data(["admin", "1qaz", "OK"],  #一组数据,每一行都会触发运行
              ["admin", "", "ERROR"],   #另一组数据
              ["1", "1qaz", "ERROR"],   #另一组数据..
              ["admin", "1234", "ERROR"],
              ["Admin", "1qaz", "ERROR"]) #实现了数据驱动,可以执行5次
    
    @ddt.unpack
    def test_ddt(self, user, passwd, expect_value):
        print(user,passwd,expect_value)
        self.assertTrue(len(user)>0)


if __name__ == __main__:
    # 执行单元测试
    unittest.main()

测试结果:

技术图片

 

 

单元测试框架unittest

标签:验证   odi   断言   rdo   python3   测试框架   cli   bsp   重构   

原文地址:https://www.cnblogs.com/hqq2019-10/p/13949230.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!