python自动化测试三部曲之unittest框架的实现

时间:2021-05-22

终于等到十一,有时间写博客了,准备利用十一这几天的假期把这个系列的博客写完

该系列文章本人准备写三篇博客

第一篇:介绍python自动化测试框架unittest

第二篇:介绍django框架+request库实现接口测试

第三篇:介绍利用Jenkins实现持续集成

今天进入第一篇,unittest框架介绍

一、unittest简述

unittest是python语言的单元测试框架,在python的官方文档中,对unittest单元测试框架进行了详细的介绍,感兴趣的读者可以到https://mand-line program that runs a set of tests; this is primarily for making test modules conveniently executable. """ # defaults for testing module=None verbosity = 1 failfast = catchbreak = buffer = progName = warnings = None _discovery_parser = None def __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=loader.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None, *, tb_locals=False): if isinstance(module, str): self.module = __import__(module) for part in module.split('.')[1:]: self.module = getattr(self.module, part) else: self.module = module if argv is None: argv = sys.argv self.exit = exit self.failfast = failfast self.catchbreak = catchbreak self.verbosity = verbosity self.buffer = buffer self.tb_locals = tb_locals if warnings is None and not sys.warnoptions: # even if DeprecationWarnings are ignored by default # print them anyway unless other warnings settings are # specified by the warnings arg or the -W python flag self.warnings = 'default' else: # here self.warnings is set either to the value passed # to the warnings args or to None. # If the user didn't pass a value self.warnings will # be None. This means that the behavior is unchanged # and depends on the values passed to -W. self.warnings = warnings self.defaultTest = defaultTest self.testRunner = testRunner self.testLoader = testLoader self.progName = os.path.basename(argv[0]) self.parseArgs(argv) self.runTests()

在unittest模块中包含的main方法,可以方便的将测试模块转变为可以运行的测试脚本。main使用unittest.TestLoader类来自动查找和加载模块内的测试用例,TestProgram类中的该部分的代码如下

def createTests(self): if self.testNames is None: self.test = self.testLoader.loadTestsFromModule(self.module) else: self.test = self.testLoader.loadTestsFromNames(self.testNames, self.module)

在执行测试用例时候,在main方法中加入了verbosity=2,代码如下

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

下面解释一下verbosity部分,在verbosity中默认是1。0代表执行的测试总数和全局结果,2代表详细的信息

四、测试套件,TestSuite

# TestSuite# 上述简单的测试会产生两个问题,可不可以控制test测试用例的执行顺序?若不想执行某个测试用例,有没有办法可以跳过?# 对于执行顺序,默认按照test的 A-Z、a-z的方法执行。若要按自己编写的用例的先后关系执行,需要用到testSuite。# 把多个测试用例集合起来,一起执行,就是testSuite。testsuite还可以包含testsuite。# 一般通过addTest()或者addTests()向suite中添加。case的执行顺序与添加到Suite中的顺序是一致的。

1、直接执行案例

我们在func.py这个文件中定义加减乘除4个测试函数

#Auther Bob#--*--conding:utf-8 --*--def add(a,b): return a + bdef minus(a,b): return a - bdef multi(a,b): return a * bdef divide(a,b): return a / b

然后在myunittest.py文件中定义我们的测试代码,这里用到了断言,我们后面会介绍

from test1 import funcclass Test2(unittest.TestCase): def setUp(self): print("前置条件") def tearDown(self): print("后置条件") def test_add(self): self.assertEqual(3,func.add(1,2)) def test_minus(self): self.assertEqual(4,func.minus(5,1)) def test_multi(self): self.assertEqual(4,func.multi(2,2)) def test_divide(self): self.assertEqual(10,func.divide(100,10))if __name__ == '__main__': unittest.main(verbosity=2)

执行结果如下

2、添加案例到测试套件中

上述简单的测试会产生两个问题,可不可以控制test测试用例的执行顺序?若不想执行某个测试用例,有没有办法可以跳过?对于执行顺序,默认按照test的 A-Z、a-z的方法执行。若要按自己编写的用例的先后关系执行,需要用到testSuite。把多个测试用例集合起来,一起执行,就是testSuite。testsuite还可以包含testsuite。一般通过addTest()或者addTests()向suite中添加。case的执行顺序与添加到Suite中的顺序是一致的。

如果用到测试套件TestSuite,则需要先写好测试代码,但是先不要执行

我们同样在myunittest.py文件中定义我们的测试代码

from test1 import funcclass Test3(unittest.TestCase): def setUp(self): print("前置条件") def tearDown(self): print("后置条件") def test_add(self): self.assertEqual(3,func.add(1,2)) def test_minus(self): self.assertEqual(4,func.minus(5,1)) def test_multi(self): self.assertEqual(4,func.multi(2,2)) def test_divide(self): self.assertEqual(10,func.divide(100,10))

我们在test_suit.py文件中引入测试案例,然后通过TestSuite类的addTests方法把测试用例添加到测试套件中

import unittestfrom test1.myunittest import Test3# from test1.myunittest2 import Test3 as t3if __name__ == '__main__': # 输出信息到控制台 # 实例化一个TestSuite类 suite = unittest.TestSuite() # 把需要执行的案例放在一个list中 tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")] # 把案例添加到实例化好的测试套件中 suite.addTests(tests) # t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")] # suite.addTests(tests) # 实例化一个参数执行类 runner = unittest.TextTestRunner(verbosity=2) # 测试执行类的实例执行测试套件 runner.run(suite)

以上的案例我们是添加一个文件的测试案例,我们同样可以添加多个文件中的案例到一个测试套件中,然后执行这个测试套件即可

import unittestfrom test1.myunittest import Test3from test1.myunittest2 import Test3 as t3if __name__ == '__main__': # 输出信息到控制台 # 实例化一个TestSuite类 suite = unittest.TestSuite() # 把需要执行的案例放在一个list中 tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")] # 把案例添加到实例化好的测试套件中 suite.addTests(tests) # 添加另外一个文件中的测试案例到测试套件中 t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")] suite.addTests(t) # 实例化一个参数执行类 runner = unittest.TextTestRunner(verbosity=2) # 测试执行类的实例执行测试套件 runner.run(suite)

上面的执行方式是输出结果到控制台,我们也可以输出结果到文件中

import unittestfrom test1.myunittest import Test3from test1.myunittest2 import Test3 as t3if __name__ == '__main__': # 输出信息到txt文件中 suite = unittest.TestSuite() tests = [Test3("test_add"), Test3("test_minus"), Test3("test_multi"), Test3("test_divide")] suite.addTests(tests) t = [t3("test_add"), t3("test_minus"), t3("test_multi"), t3("test_divide")] suite.addTests(t) with open('UnittestTextReport.txt', 'a') as f: runner = unittest.TextTestRunner(stream=f, verbosity=2) runner.run(suite)

3、直接添加测试类到测试套件中

案例一个一个添加还是比较麻烦,我们可以直接添加一个测试类到测试套件中

利用下面的方法加载一个测试类

unittest.TestLoader().loadTestsFromTestCase(t3)import unittestfrom unittest import TestLoaderfrom test1 import myunittestfrom test1.myunittest2 import Test3 as t3if __name__ == '__main__': suite = unittest.TestSuite() loader = TestLoader() test_cases1 = unittest.TestLoader().loadTestsFromTestCase(t3) # 参数是一个类,而这个类必须是unittest.TestCase的子类或者孙类 suite.addTests(test_cases1) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)

4、直接加载一个模块到测试套件中,如果这个模块中有多个类,则会把所有的类的测试案例加载到测试套件中

unittest.TestLoader().loadTestsFromModule(myunittest)import unittestfrom unittest import TestLoaderfrom test1 import myunittestfrom test1.myunittest2 import Test3 as t3if __name__ == '__main__': suite = unittest.TestSuite() loader = TestLoader() test_cases1 = unittest.TestLoader().loadTestsFromModule(myunittest) # 参数是一个模块,会把这个模块里的所有case加载进来 suite.addTests(test_cases1) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)

我给大家截图看下

5、通过案例名称添加案例到测试套件中

test_cases1 = unittest.TestLoader().loadTestsFromName('test1.myunittest2.Test3.test_minus') import unittestfrom unittest import TestLoaderfrom test1 import myunittestfrom test1.myunittest2 import Test3 as t3if __name__ == '__main__': suite = unittest.TestSuite() loader = TestLoader() test_cases1 = unittest.TestLoader().loadTestsFromName('test1.myunittest2.Test3.test_minus') # 加载某个cese runner = unittest.TextTestRunner(verbosity=2) suite.addTests(test_cases1) runner.run(suite)

我截图给大家看下目录结构

五、忽略执行案例

在实际的项目中,有些案例我们可能暂时不需要执行,如果有这样的问题,我们该怎么办,unittest框架已经为我们提供了解决方案

1、无条件跳过该案例,用该装饰器修饰要执行的案例,则该案例会被忽略不执行

@unittest.skip("do not exec") @unittest.skip("do not exec") # 无条件跳过执行该案例 def test_add(self): self.assertEqual(3,func.add(1,2))

2、满足某个条件才跳过该案例

@unittest.skipIf(4 > 3,"2 > 3 do not exec") @unittest.skipIf(4 > 3,"2 > 3 do not exec") # 满足某个条件才跳过执行 def test_minus(self): self.assertEqual(4,func.minus(5,1))

3、不满足某个条件才跳过案例

@unittest.skipUnless(4 < 3,"hahah") @unittest.skipUnless(4 < 3,"hahah") # 不满足某个条件才跳过执行 def test_multi(self): self.assertEqual(4,func.multi(2,2))

4、我们也可以在案例里面定义忽略执行这条案例

def test_divide(self): self.skipTest("wydd") self.assertEqual(10,func.divide(100,10))

六、断言

断言就是判断实际测试结果与预期结果是否一致,一致则测试通过,否则失败。因此,在自动化测试中,无断言的测试用例是无效的,这是因为当一个功能自动化已经全部实现,在每次版本迭代中执行测试用例时,执行的结果必须是权威的,也就是说自动化测试用例执行结果应该无功能性或者逻辑性问题,在自动化测试中最忌讳的就是自动化测试的用例虽然是通过的,但是被测试的功能却是存在问题的,自动化测试用例经常应用在回归测试中,发现的问题不是特别多,如果测试结果存在功能上的问题,则投入了人力去做的自动化参数就没有多大的意义了,所以每一个测试用例必须要有断言;在测试的结果中只有两种可能,一种是执行通过,另外一种是执行失败,也就是功能存在问题,在TestCase类中提供了assert方法来检查和报告失败,常用的方法如下

self.assertEqual(3,func.add(1,2)) # 判断是否相等 self.assertNotEqual() # 判断是否不等于 self.assertTrue() # 判断布尔值是否为True self.assertFalse() # 判断布尔值是否为False self.assertIs() # 判断类型是否相同 self.assertIsNot() # 判断类型是否不同 self.assertIsNone() # 判断是否为None self.assertIsNotNone() # 判断是否不为None self.assertIn() # 判断在某个范围内 self.assertNotIn() # 判断是否不在某个范围内 self.assertIsInstance() # 判断是否为某个类的实例 self.assertNotIsInstance()

到此这篇关于python自动化测试三部曲之unittest框架的实现的文章就介绍到这了,更多相关python unittest框架内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章