zoukankan      html  css  js  c++  java
  • 使用python的unittest做测试

    文档地址http://docs.python.org/library/unittest.html

    第一个例子直接引用文档中的例子,其他的简略的写了写结论性的东西,具体的参考python_testing_cookbook一书。

    一、简单的例子

    View Code
     1 import random
    2 import unittest
    3
    4 class TestSequenceFunctions(unittest.TestCase):
    5
    6 def setUp(self):
    7 self.seq = range(10)
    8
    9 def test_shuffle(self):
    10 # make sure the shuffled sequence does not lose any elements
    11 random.shuffle(self.seq)
    12 self.seq.sort()
    13 self.assertEqual(self.seq, range(10))
    14
    15 # should raise an exception for an immutable sequence
    16 self.assertRaises(TypeError, random.shuffle, (1,2,3))
    17
    18 def test_choice(self):
    19 element = random.choice(self.seq)
    20 self.assertTrue(element in self.seq)
    21
    22 def test_sample(self):
    23 with self.assertRaises(ValueError):
    24 random.sample(self.seq, 20)
    25 for element in random.sample(self.seq, 5):
    26 self.assertTrue(element in self.seq)
    27
    28 if __name__ == '__main__':
    29 unittest.main()

    实现一个继承unittest.TestCase的类,使用unittest.main()来测试该类中所有以test开头的测试用例。

    简单的assert方法有如下:
    self.assertEquals(100, value)
    self.assertTrue(value == 0)
    self.assertFalse(value > 0
    self.assertRaises(TypeError, value.convert_to_decimal)

    在写测试用例的时候尽量使用assertEquals而不是assertTrue、assertFalse,当assertEquals失败的时候,会打印出比较的两方值更直观

    self.fail([msg])会无条件的导致测试失败,不推荐使用。

    下面的例子的写法是要避免发生:

    View Code
    1 import unittest
    2 class BadTest(unittest.TestCase):
    3 def test_no_roman_numeral(self):
    4 value = RomanNumeralConverter(None)
    5 try:
    6 value.convert_to_decimal()
    7 self.fail("Expected a TypeError")
    8 except TypeError, e:
    9 pass

    这个时候推推荐使用assertRaises

    二、使用setUp和tearDown

    每次运行test方法时,先用setUp初始化程序,然后运行test方法,最后使用tearDown清理程序
    def setUp(self):
        print "Creating a new RomanNumeralConverter..."
        self.cvt = RomanNumeralConverter()

    def tearDown(self):
        print "Destroying the RomanNumeralConverter..."
        self.cvt = None

    如果不同的方法需要不同的setUp和tearDown方法,那么只好写过个测试用例了。

    三、使用比unittest.main()更详细的运行测试用例的方法

    if __name__ == "__main__":
      suite = unittest.TestLoader().loadTestsFromTestCase( \
                     RomanNumeralConverterTest)
      unittest.TextTestRunner(verbosity=2).run(suite)

    python使用unittest.TestLoader().loadTestsFromTestCase方法获取RomanNumeralConverterTest的所有test方法
    然后通过TextTestRunner来运行

    四、运行部分测试方法

    View Code
     1 if __name__ == "__main__":
    2 import sys
    3 suite = unittest.TestSuite()
    4 if len(sys.argv) == 1:
    5 suite = unittest.TestLoader().loadTestsFromTestCase(\
    6 RomanNumeralConverterTest)
    7 else:
    8 for test_name in sys.argv[1:]:
    9 suite.addTest(\
    10 RomanNumeralConverterTest(test_name))
    11 unittest.TextTestRunner(verbosity=2).run(suite)

    五、一次运行多个测试用例

    View Code
    1 if __name__ == "__main__":
    2 import unittest
    3 from recipe5 import *
    4 suite1 = unittest.TestLoader().loadTestsFromTestCase( \
    5 RomanNumeralConverterTest)
    6 suite2 = unittest.TestLoader().loadTestsFromTestCase( \
    7 RomanNumeralComboTest)
    8 suite = unittest.TestSuite([suite1, suite2])
    9 unittest.TextTestRunner(verbosity=2).run(suite)

    六、在test model 中 使用test suites

    View Code
     1 def high_and_low():
    2 suite = unittest.TestSuite()
    3 suite.addTest(\
    4 RomanNumeralConverterTest("test_parsing_millenia"))
    5 suite.addTest(\
    6 RomanNumeralConverterTest("test_parsing_one"))
    7 return suite
    8
    9 def combos():
    10 return unittest.TestSuite(map(RomanNumeralConverterTest,\
    11 ["test_combo1", "test_combo2", "test_combo3"]))
    12
    13 def all():
    14 return unittest.TestLoader().loadTestsFromTestCase(\
    15 RomanNumeralConverterTest)
    16
    17 if __name__ == "__main__":
    18 for suite_func in [high_and_low, combos, all]:
    19 print "Running test suite '%s'" % suite_func.func_name
    20 suite = suite_func()
    21 unittest.TextTestRunner(verbosity=2).run(suite)

    七、将已有的测试代码迁移到unittest

    不使用unittest

    View Code
     1 from recipe7 import *
    2
    3 class RomanNumeralTester(object):
    4 def __init__(self):
    5 self.cvt = RomanNumeralConverter()
    6
    7 def simple_test(self):
    8 print "+++ Converting M to 1000"
    9 assert self.cvt.convert_to_decimal("M") == 1000
    10
    11 def combo_test1(self):
    12 print "+++ Converting MMX to 2010"
    13 assert self.cvt.convert_to_decimal("MMXX") == 2010
    14
    15 def combo_test2(self):
    16 print "+++ Converting MMMMDCLXVIII to 4668"
    17 val = self.cvt.convert_to_decimal("MMMMDCLXVII")
    18 self.check(val, 4668)
    19
    20 def other_test(self):
    21 print "+++ Converting MMMM to 4000"
    22 val = self.cvt.convert_to_decimal("MMMM")
    23 self.check(val, 4000)
    24
    25 def check(self, actual, expected):
    26 if (actual != expected):
    27 raise AssertionError("%s doesn't equal %s" % \
    28 (actual, expected))
    29
    30 def test_the_system(self):
    31 self.simple_test()
    32 self.combo_test1()
    33 self.combo_test2()
    34 self.other_test()
    35
    36 if __name__ == "__main__":
    37 tester = RomanNumeralTester()
    38 tester.test_the_system()

    迁移到unittest

    View Code
     1 from recipe7 import *
    2 from recipe7_legacy import *
    3 import unittest
    4
    5 if __name__ == "__main__":
    6 tester = RomanNumeralTester()
    7
    8 suite = unittest.TestSuite()
    9 for test in [tester.simple_test, tester.combo_test1, \
    10 tester.combo_test2, tester.other_test]:
    11 testcase = unittest.FunctionTestCase(test)
    12 suite.addTest(testcase)
    13
    14 unittest.TextTestRunner(verbosity=2).run(suite)

    八、简单化

    一个测试函数里面写一个assert***,便于查看bug

    九、测试边缘

    比如测试一个到4000为止的整数,需要测试
    1,4000, 0 4001, -1, None, 1.2
    错误的输入也是必要的

    通过迭代测试边缘

    View Code
     1 def test_bad_inputs(self):
    2 r = self.cvt.convert_to_roman
    3 d = self.cvt.convert_to_decimal
    4 edges = [("equals", r, "", None),\
    5 ("equals", r, "I", 1.2),\
    6 ("raises", d, TypeError, None),\
    7 ("raises", d, TypeError, 1.2)\
    8 ]
    9 [self.checkout_edge(edge) for edge in edges]
    10
    11 def checkout_edge(self, edge):
    12 if edge[0] == "equals":
    13 f, output, input = edge[1], edge[2], ed
    14 print("Converting %s to %s..." % (input
    15 self.assertEquals(output, f(input))
    16 elif edge[0] == "raises":
    17 f, exception, args = edge[1], edge[2],
    18 print("Converting %s, expecting %s" % \
    19 (args, exception))
    20 self.assertRaises(exception, f, *args)

  • 相关阅读:
    BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】
    SPOJ QTree【树链剖分】
    BZOJ_1503 [NOI2004]郁闷的出纳员 【Splay树】
    Hibernate学习实例
    Educational Codeforces Round 64 C. Match Points 【二分思想】
    ramn 备份操作
    表值函数--自定义工作日历
    删除win10开始菜单中程序的目录
    C#自定义注释自动生成模板注释
    oralce知识第三章
  • 原文地址:https://www.cnblogs.com/imouren/p/2127997.html
Copyright © 2011-2022 走看看