单元测试模块unittest使用学习

工作原理:
unittest中最核心的四个概念是:test case, test suite, test runner, test fixture。

一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),
执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。 而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。 TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。 TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite
/TestCase中的run(result)方法。 测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。 而对一个测试用例环境的搭建和销毁,是一个fixture。

三个模块:
1、程序

def add(a, b):
    return a+b

def minus(a, b):
    return a-b

def multi(a, b):
    return a*b

def divide(a, b):
    return a/b

2、测试用例

class TestMathFunc(unittest.TestCase):# 一个class继承了unittest.TestCase,便是一个测试用例,但如果其中有多个以 test 开头的方法,那么每有一个这样的方法,在load的时候便会生成一个TestCase实例

    def test_add(self):  # 每个测试方法都需要以test开头,否则是不会被unittest识别到
          """Test method add(a, b)"""
          self.assertEqual(3, add(1, 2))  # 判断相等
          self.assertNotEqual(3, add(2, 2))  # 判断不相等
    def test_minus(self):
        """Test method minus(a, b)"""
        self.assertEqual(1, minus(3, 2))

    def test_multi(self):
        """Test method multi(a, b)"""
        self.assertEqual(6, multi(2, 3))

      def test_divide(self):
        """Test method divide(a, b)"""
        self.assertEqual(2, divide(6, 3))
        self.assertEqual(2.5, divide(5, 2))


 if __name__ == '__main__':
    unittest.main() #main传参控制报告详细程度  verbosity = ,默认是1,不输出每一条测试用例的结果是0,输出详细的测试用例执行结果是2

3、执行测试

import unittest
from test_mathfunc import TestMathFunc #传入测试用例,

if __name__=='__main__':
  suite = unittest.TestSuite()

  #按指定顺序执行
  tests = [TestMathFunc("test_add"),TestMathFunc("test_minus"),TestMathFunc('test_divide')]
  suite.addTests(tests)

  # 直接用addTest方法添加单个TestCase
  # suite.addTest(TestMathFunc("test_multi"))

  # 用addTests + TestLoader
  # loadTestsFromName(),传入'模块名.TestCase名'
  # suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
  # suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc']))  # loadTestsFromNames(),类似,传入列表

  # loadTestsFromTestCase(),传入类TestCase
  # suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))

  runner = unittest.TextTestRunner(verbosity=2) #测试结果展示内容
  runner.run(suite) #执行测试

测试用例的保存:

修改执行测试文件:

import
unittest from test_mathfunc import TestMathFunc if __name__=='__main__': suite = unittest.TestSuite() # tests = [TestMathFunc("test_add"),TestMathFunc("test_minus"),TestMathFunc('test_divide')] # suite.addTests(tests) # 直接用addTest方法添加单个TestCase # suite.addTest(TestMathFunc("test_multi")) # 用addTests + TestLoader # loadTestsFromName(),传入'模块名.TestCase名' # suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc')) # suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),类似,传入列表 # loadTestsFromTestCase(),传入leiTestCase suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) with open('test_Report.txt','a') as f: #打开要保存结果的文件 runner = unittest.TextTestRunner(stream=f,verbosity=2)#stream 写入内容 runner.run(suite)

准备环境、清理环境:

test fixture之setUp() 和tearDown()

这两个方法在每个测试方法执行前以及执行后执行一次

修改测试用例文件

import unittest
from mathfunc import *


class TestMathFunc(unittest.TestCase):
    """Test mathfuc.py"""

    def setUp(self):  #setUp用来为测试准备环境
        print "do something before test.Prepare environment."

    def tearDown(self): #tearDown 用来清理测试环境
        print "do something after test.Clean up."

    def test_add(self):
        """Test method add(a, b)"""
        print "add"
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(2, 2))

    def test_minus(self):
        """Test method minus(a, b)"""
        print "minus"
        self.assertEqual(1, minus(3, 2))

    def test_multi(self):
        """Test method multi(a, b)"""
        print "multi"
        self.assertEqual(6, multi(2, 3))

    def test_divide(self):
        """Test method divide(a, b)"""
        print "divide"
        self.assertEqual(2, divide(6, 3))
        self.assertEqual(2.5, divide(5, 2))

如果想要在所有case执行之前准备一次环境,并在所有case执行结束之后再清理环境,我们可以用 setUpClass() 与 tearDownClass():

class TestMathFunc(unittest.TestCase):
    """Test mathfuc.py"""

    @classmethod
    def setUpClass(cls): #执行测试前运行
        print ("This setUpClass() method only called once.")
    @classmethod
    def tearDownClass(cls): #所有测试用例执行完毕后运行
        print ("This tearDownClass() method only called once too.")

    def test_add(self):
        """Test method add(a, b)""" 
        print ("add")
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(2, 2))

跳过当前用例:

1.skip装饰器:

class TestMathFunc(unittest.TestCase):
    """Test mathfuc.py"""

    ...

    @unittest.skip("I don't want to run this case.")
    def test_divide(self):
        """Test method divide(a, b)"""
        print "divide"
        self.assertEqual(2, divide(6, 3))
        self.assertEqual(2.5, divide(5, 2))

unittet可以分无条件忽略和有条件忽略,通过装饰器实现
@unittest.skip(reason): skip(reason)装饰器:无条件跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipIf(reason): skipIf(condition,reason)装饰器:条件为真时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipUnless(reason): skipUnless(condition,reason)装饰器:条件为假时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.expectedFailure(): expectedFailure()测试标记为失败。

@self.skipTest :函数体内使用,

class MyTestCase(unittest.TestCase):  
    @unittest.skip("demonstrating skipping")  
    def test_nothing(self):  
        self.fail("shouldn't happen")  
    @unittest.skipIf(mylib.__version__ < (1, 3),  
                     "not supported in this library version")  
    def test_format(self):  
        # Tests that work for only a certain version of the library.  
        pass  
    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")  
    def test_windows_support(self):  
        # windows specific testing code  
        pass  
    @unittest.expectedFailure()  
      def test_windows_support(self):  
        # windows specific testing code  
        pass
    def test_divide(self):
        """Test method divide(a, b)"""
        self.skipTest('Do not run this.')
        print "divide"
        self.assertEqual(2, divide(6, 3))
        self.assertEqual(2.5, divide(5, 2))

忽略测试类:

@unittest.skip("showing class skipping")  
class MySkippedTestCase(unittest.TestCase):  
    def test_not_run(self):  
        pass

输出测试HTML报告 :HTMLTestRunner

修改执行测试文件:
# -*- coding: utf-8 -*-

import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner #引入HTMLtestrunner

if __name__ == '__main__':
    suite = unittest.TestSuite() 
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) # 执行testmathfunc

    with open('HTMLReport.html', 'w') as f: 
        runner = HTMLTestRunner(stream=f, #写入HTML文件
                                title='MathFunc Test Report', #运行状况
                                description='generated by HTMLTestRunner.', #执行结果
                                verbosity=2
                                )
        runner.run(suite)

另一种输出方式:

# -*- coding: utf-8 -*-
import unittest,time
from HTMLTestRunner import HTMLTestRunner
from email.mime.text import MIMEText
from email.header import Header
import smtplib
test_dir='./test_jb/' #目录路径
discover=unittest.defaultTestLoader.discover(test_dir,pattern='test_*.py') #查找当前目录下的所有以test_开头的文件,并执行

if __name__=='__main__':
    now=time.strftime('%Y-%m-%d %H_%M_%S')#当前日期
    filename=test_dir+now+'result.html' #名称后缀
    fp=open(filename,'wb') #写入内容
    runner=HTMLTestRunner(stream=fp,title='测试报告',description='用例执行情况') #执行测试方式
    runner.run(discover)# 执行测试
    fp.close() #关闭测试

原文地址:https://blog.csdn.net/huilan_same/article/details/52944782

 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/yc-c/p/9155888.html