python unittest模块使用

python unittest模块使用

学习完本篇,你将会

  • 编写python单元测试用例
  • 独立编写加减乘数的测试用例,同时满足一定条件可以跳过用例

简单认识单元测试

#例一:
#计算器类
Class count:
    def __init__(self,a,b):
	self.a = int(a)
	self.b = int(b)
#计算加法
    def add(self):
	return self.a+self.b
#测试类一:
#计算器类
Class TestCount:
     def test_add(self):
            try:
                   j=Count(2,3)
                   add=j.add()
                   assert(add == 5),’Interger addition result error’
             except ArrertioError as msg;
                    print msg
             else:
                     print ‘Test pass’
#执行测试类的测试方法
mytest = TestCount()
mytest.test_add()

#测试类二:
from calulator import Count
Import unittest
class TestCount(unittest.TestCase):
     def setUp(self):
            print “test start”
     
     def test_add(self):
             j = Count(2,3)
             self.assertEqual(j.add(),5)

      def tearDown(self):
             print “teset end”
If __name__ == ‘__main__’:
        unittest.main()
  • 通过比较上述的两种方法,可以看出测试类一虽然可以测试,单测试添加测试用例部方便(目前是尝试2,3,如果再添加需要增加很多代码),测试类二添加测试用例方面,可以随时添加。
  • 测试类二中,unittest可以直接把TestCount中以“test”命令的脚本直接识别为测试方法,并且执行它们
  • 通过也印证了在pycharm含有test命名的函数,执行并不是按照我们要求的顺序执行

unittest简介以及安装

  • 单元测试(unit testing):指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,单元就是人为规定的最小的被测功能模块。
  • Python单元测试框架(The Python unit testing framework):简称为PyUnit,是Kent Beck和Erich Gamma这两位所设计的 Junit 的Python版本。
  • unittest环境要求: PyUnit可以在Python 1.5.2及更高版本上运行。
  • unittest安装:python1.5.2以上的版本,python自带unittest模块,查看python是否包含unittest模块,通过D:\Python27\Lib\unittest,看是否含有unittest,如果没有需要下载安装,或者copy unittest模块。

Unittest中一些重要概论

  • Test Case:Test Case的实例就是一个测试用例。一个完成的是测试用例的流程包含:1、测试前环境的搭建(setUp)、实现测试过程的代码(run),以及测试后环境的还原(tearDown)。
  • Test Suit:验证一个功能往往需要多个用例,这些用例集合在一起叫测试套。Test Suit用来组装多个用例。可以通过addTest加载TestCase到TestSuite中,从而返回一个TestSuit实例。
  • Test Runner:测试执行也是单元测试中非常重要的一个概念,一般的单元测试框架都会提供一个丰富的执行策略和执行结果。在unittest单元测试框架中,通过TextTestRunner类提供的run()方法来执行test suit/test case。
  • Test Fixture:一个测试用例环境搭建和销毁,就是一个fixture。比如测试用例想访问数据库,可以通过setUp中连接数据库,在tearDown中关闭数据库即可。

Unittest例子

from calculator import count
import unittest
class TestCount(unittest.TestCase):
	def setUp(self):
		print “test start”
	def test_add1(self):
		j=Count(2,3)
		self.assertEqual(j.add(),5)
	def test_add2(self):
		j=Coun(47,76) 
		self.assertEqual(j.add(),117)
	def tearDown(self):
		print “test end”

If __name__ == ‘__main__’:
	suite = unittest.TestSuite()
	suite.addTest(TestCount(“test_add2”))
	runner = unittest.TextTestRunner()
	runner.run(suite)

调用Unittest框架的TestSuit()类来创建测试套件,通过它所提供的addTest()方法来添加测试用例测试test_add2()。调用

断言方法

方法 检查
assertEqual(a,b) a=b
assertNoEqual(a,b) a!=b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a,b) a is b
assertIsNot(a,b) a is not b
assertIsNone a is None
assertIsNoNone(x) a is not None
assertIn(a,b) a in b
assertNotIn(a,b) a not in b
assertIsInstance(a,b) isinstance(a,b)
assertIsInstance(a,b) not is instance(a,b)

断言实例一

  • 语法:assertEqual(first,second,msg)
实例:
import unittest
class Test(unittest.TestCase):
     def setUp(self):
          num = input(“Enter a number:”)
          self.number = int(number)

     def test_case(self):
       self.assertEqual(self.number,10,msg=”your input is not 10”)

     def tearDown(self):
         pass

if __name__== “__main__”:
      unittest.main()
图1

说明:用例先执行setUp前置条件,再执行测试用例test_case,再执行tearDown条件恢复。
arrertEqual:比较两个数的值是否相等,如果不相等输出msg中定义的提示信息,并执行以下结果:

断言实例二

  • 语法:assertTrue(表达式,msg)
实例:
#用于判断质数
def is_prime(n):
       if n<=1:
           return False
       for i in range(2,n):
            if n%i == 0:
                 return False
       return Ture

import unittest
class Test(unittest.TestCase):
     def setUp(self):
          self.number = int(number)

     def test_case(self):
       self.assertTrue(is_prime(7),msg=”Is not prime!”)

     def tearDown(self):
         pass

if __name__== “__main__”:
      unittest.main()
图1 图1

说明:用例先执行setUp前置条件,再执行测试用例test_case,再执行tearDown条件恢复。
arrertTrue:比较Bool是否为Ture,如果不是输出msg中定义的提示信息,并执行以下结果:

断言实例三

  • 语法:assertIn(first,second,msg=None)
实例:
#用于判断质数
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 is not in b”)

     def tearDown(self):
         print “test end”

if __name__== “__main__”:
      unittest.main()
图3 图4

unittest组织单元测试用例

例一

calulartor.py:
class Count():
    def __init__(self,a,b):
         self.a = int(a)
         self.b = int(b)

   #计算加法
   def add(self):
         return self.a+self.b

  #计算减法
   def sub(self):
         return self.a - self.b
test.py:
from calculator import Count
import unittest
class TestAdd(unittest.TestCase):
    def setUp(self):
         print “test add start”

   def test_add1(self):
          j = Count(2,3) 
          self.assertEqula(j.add(),5) 

   def test_add2(self):
          j = Count(41,76) 
          self.assertEqula(j.add(),117)  

   def tearDown(self):
         print “test add end” 
class TestSub(unittest.TestCase):
         def setUp(self):
                print (“test sub start”)
         
         def test_sub1(self):
                 j = Count(2,3)
         
        def test_sub2(self):
                 j = Count(71,46) 
                 self.assertEqual(j.sub(),25)

         def tearDown(self):
                print “test sub end”
if __name__ == '__main__':
     #构造测试集
     suite = unittest.TestSuite()
     suite.addTest(TestAdd(“test_add1”))
     suite.addTest(TestAdd(“test_add2”))
     suite.addTest(TestSub(“test_sub1”))
     suite.addTest(TestSub(“test_sub2”))

     #运行测试集合

     runner =  unittest.TextTestRunner ()
     runner.run(suite)

TestSuit:TestSuit类中addTest()方法把不同测试类中的测试方法组装到测试套件中。通过运行测试套件,来执行所有的测试用例
通过运行可得知每次setUp以及tearDown都会被执行,如果用例很多初始化执行以及恢复条件都是一样,可以通过继承的方式可大大提高编写用例效率

例二

calulartor.py:
class Count():
    def __init__(self,a,b):
         self.a = int(a)
         self.b = int(b)

   #计算加法
   def add(self):
         return self.a+self.b

  #计算减法
   def sub(self):
         return self.a - self.b
test.py:
from calculator import Count
import unittest
class TestAdd(unittest.TestCase):
    def setUp(self):
         print “test add start”

   def test_add1(self):
          j = Count(2,3) 
          self.assertEqula(j.add(),5) 

   def test_add2(self):
          j = Count(41,76) 
          self.assertEqula(j.add(),117)  

   def tearDown(unittest.TestCase):
         print “test add end” 

class TestSub(unittest.TestCase):
         def setUp(self):
                print (“test sub start”)
         
         def test_sub1(self):
                 j = Count(2,3)
         
        def test_sub2(self):
                 j = Count(71,46) 
                 self.assertEqual(j.sub(),25)

         def tearDown(self):
                print “test sub end”
if __name__ == '__main__':
     #构造测试集
     suite1 = unittest.TestLoader().LoadTestsFromTestCase(TestAdd)     
     suite2 = unittest.TestLoader().LoadTestsFromTestCase(TestSub)                    
     suite = unittest.TestSuite([suite1,suite2])
     #运行测试集合
     unittest.TextTestRunner ()
     runner.run(suite)

TestLoader:用来加载TestCase到TestSuite中的,其中有几个 loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例;

discover自动发现用例

通过上述suite方式提供构造用例,如果用例数少,比较方便,但自动化设计一般情况下用例数都达到成百上千条用例,这个时候就比较麻烦。unittest提供一个单元测试框架自动识别测试用例,TestLoad类中提供了discover方法来自动识别测试用例。

  • 语法: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。
runtest.py例子:
import unittest
#定义测试用例的目录为当前目录
test_dir ='./'
discover = unittest.defaultTestLoad.discover(test_dir,pattern = 'test*.py')

if __name__ == '__main__':
       runner = unittest.TextTestRunner()
       runner.run(discover)

用例执行顺序

test.py:
import unittest
class TestBdd(unittest.TestCase):
        def setUp(self):
               print “test TestBdd”

        def test_ccc(self):
               print “test ccc”

        def test_aaa(self):
               print “test aaa”

         def tearDown(self):
               pass

class TestAdd(unittest.TestCase):
         def setUp(self):
              print “test TestAdd:”
         
         def test_bbb(self):
              print “test bbb”

         def test_ddd(self):
              print “test   ddd”
         
         def tearDown(self):
               pass

if __name__ == '__main__':
         unittest.main() 
通过unittest.TestSuite方法
if __name__ == '__main__':
     #构造测试集
     suite = unittest.TestSuite()
     suite.addTest(TestBdd(“test_ccc”))
     suite.addTest(TestAdd(“test_bbb”))
     suite.addTest(TestBdd(“test_aaa”))
     suite.addTest(TestAdd(“test_ddd”))

     #运行测试集合

     runner =  unittest.TestSuite()
     runner.run(suite)
  • 通过运行发现,使用unittest.mian()
    的方式,无论运行多少次都按照一定方式来执行,而且每次顺序都是一样,而通过unittest.TestSuite的方式是按照加载的顺序执行。
  • 通过默认的方式运行是按照ASCII的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。因此没有按照用例从上到下的顺序执行。而通过unittest.TestSuite是按照加载的顺序执行。

fixtures学习

test.py:
import unittest
def setUpModule():
      print “test module start.......”

def tearDownModule():
      print “test module end.......”

class Test(unittest.TestCase):
        @classmethod
         def setUpClass(cls):
                print “test class start.......”

        @classmethod
         def tearDownClass(cls):
                print “test class end.......”

        def setUp(self):
               print “test case...start”

       def tearDown(self):
               print “test case...end”

        def test_case1(self):
               print “test case1”

        def test_case2(self):
               print “test case2”
 
if __name__ == '__main__':
         unittest.main() 
  • fixtures可以理解为夹心饼干外层的两片饼干,这里两片饼干就是setUp/tearDown,中间的心就是测试用例
  • setUpModule/tearDownModule:在整个模块的开始与结束时被执行
  • setUpClass/tearDownClass:在测试类开始与结束时被执行
  • setUp/tearDown:在测试用例的开始与结束时被执行
posted @ 2021-09-20 23:51  IT策士  阅读(386)  评论(0编辑  收藏  举报