import unittest
class MyTest(unittest.TestCase):
@unittest.skip("直接跳过测试")
def test_skip(self):
print("test aaa")
@unittest.skipIf(3>2,"当条件为真时跳过测试")
def test_skip_if(self):
print('test bbb')
@unittest.skipUnless(3>2,"当条件为真时执行测试")
def test_skip_unless(self):
print('test ccc')
@unittest.expectedFailure
def test_expected_failure(self):
self.assertEqual(2,3)
if __name__ == '__main__':
unittest.main()
unittest提供了可以共享的defaultTestLoader类,可以使用其子类或方法创建实例,discover()方法就是其中之一。
unittest.defaultTestLoader.discover(start_dir,pattern='test*.py',top_level_dir=None)
找到指定目录及其子目录下的所有测试模块,只有匹配的文件名才能被加载。如果启动的不是顶层目录,那么顶层目录必须单独指定。
- start_dir:待测试的模块名或测试用例目录。
- pattern='test.py':测试用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件,星号“”表示任意多个字符。
- top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,则默认为None。
测试用例的执行顺序涉及多个层级:多个测试目录>多个测试文件>多个测试方法(测试用例)。unittest提供的main()方法和discover()方法是按照什么顺序查找测试用例的呢?
其实,unittest默认根据ASCII码的顺序加载测试用例的(数字与字母的顺序为0~9,A~Z,a~z),所以TestAdd类会优先于TestBdd类被执行,testaaa()方法会优先于test_ccc()方法被执行,也就是说,它并不是按照测试用例的创建顺序从上到下执行的。
discover()方法和main()方法的执行顺序是一样的。对于测试目录与测试文件来说,上面的规律同样适用。test_aaa.py文件会优先于test_bbb.py文件被执行。所以,如果想让某个测试文件先执行,可以在命名上加以控制。
当然,也可以用到前面介绍过的测试套件TestSuite,通过addTest()方法将测试用例加入测试套件,则会按照套件里的添加顺序去加载测试用例。
不过,当测试用例非常多时,不推荐用这种方法创建测试套件,最好的方法是通过命名控制执行顺序。如果测试用例在设计时不产生相互依赖,那么测试用例的执行顺序就没那么重要了。
以下抛弃了unittest提供的main()方法,调用TestSuite类下面的addTest()来添加测试用例。然后将Testsuite放入TestRunner里面进行启动。
import unittest
import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self): #Test Fixture-每条用例开始执行前,执行该方法
print("开始执行测试")
def tearDown(self): #Test Fixture-每条用例结束执行后,执行该方法
print("执行测试结束")
def test_add(self):
result = Calculator.Add(1, 2)
self.assertEqual(result, 3)
def test_sub(self):
result = Calculator.Substract(5, 1)
self.assertEqual(result, 4)
def test_mul(self):
result = Calculator.Multiply(5, 1)
self.assertEqual(result, 6)
def test_div(self):
result = Calculator.Divide(6, 2)
self.assertEqual(result, 3)
if __name__ == '__main__':
#创建测试套件TestSuite
suit = unittest.TestSuite()
suit.addTest(TestCalculator("test_add"))
suit.addTest(TestCalculator("test_sub"))
suit.addTest(TestCalculator("test_mul"))
suit.addTest(TestCalculator("test_div"))
#创建测试运行期TestRunner
runner = unittest.TextTestRunner()
runner.run(suit)
这样做比直接使用main()方法要麻烦得多,但也有优点,可灵活的控制用例的执行顺序。
不过一个一个地添加测试用例到测试套件中,有点麻烦,所以可以把要执行的测试用例用个列表来管理,然后再把这个列表添加到测试套件中
import unittest
import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self): #Test Fixture-每条用例开始执行前,执行该方法
print("开始执行测试")
def tearDown(self): #Test Fixture-每条用例结束执行后,执行该方法
print("执行测试结束")
def test_add(self):
result = Calculator.Add(1, 2)
self.assertEqual(result, 3)
def test_sub(self):
result = Calculator.Substract(5, 1)
self.assertEqual(result, 4)
def test_mul(self):
result = Calculator.Multiply(5, 1)
self.assertEqual(result, 6)
def test_div(self):
result = Calculator.Divide(6, 2)
self.assertEqual(result, 3)
if __name__ == '__main__':
# 构造测试套件
suite = unittest.TestSuite()
test_cases = [TestCalculator("test_add"), TestCalculator("test_sub"), TestCalculator("test_div")]
suite.addTests(test_cases)
# 执行测试
runner = unittest.TextTestRunner(
verbosity=2) # verbosity 参数可以控制输出的错误报告的详细程度,默认是 1;如果设为 0,则不输出每一用例的执行结果;如果设为 2,则输出详细的执行结果
runner.run(suite)
unittest的setup、teardown会在每个用例执行前后执行一次,如上面测试用例类中有4个测试用例,
那么每个用例执行前会执行setup,执行后会执行teardown,即setup、teardown总共会调用4次,
但考虑实际自动化测试场景,多个用例只需执行一次setup,全部用例执行完成后,执行一次teardown,
针对该种场景,unittest的处理方法是使用setupclass、teardownclass,注意@classmethod的使用,
|