1. 程式人生 > >Python+Unittest+自動化:使用Python進行單元測試

Python+Unittest+自動化:使用Python進行單元測試

unittest單元測試框架不僅可以適用於單元測試,還可以將其用於自動化測試用例的開發與執行,該測試框架可組織執行測試用例,並且提供了豐富的斷言方法,判斷測試用例是否通過,最終生成測試結果。

1.Unitest單元測試

對於單元測試,需要設定預先條件,對比預期結果和實際結果。

unittest庫提供了testSuite、testCase、testRunner、Skip等,具體有以下作用:

1.1 testSuite 測試套件

    testSuite = unittest.TestSuite() testSuite.addTest()

1.2 testCase 測試用例

測試用例是一個完整的測試流程,包括測試前準備環境的搭建(setUp),執行測試程式碼(run),測試後環境的還原(tearDown),以及判斷測試得到的實際結果和預期結果是否相等決定的的assert*():
assertEqual(a,b,[msg='測試失敗時列印的資訊']):斷言a和b是否相等,相等則測試用例通過。
assertNotEqual(a,b,[msg='測試失敗時列印的資訊']):斷言a和b是否相等,不相等則測試用例通過。
assertTrue(x,[msg='測試失敗時列印的資訊']):斷言x是否True,是True則測試用例通過。
assertFalse(x,[msg='測試失敗時列印的資訊']):斷言x是否False,是False則測試用例通過。
assertIs(a,b,[msg='測試失敗時列印的資訊']):斷言a是否是b,是則測試用例通過。
assertNotIs(a,b,[msg='測試失敗時列印的資訊']):斷言a是否是b,不是則測試用例通過。
assertIsNone(x,[msg='測試失敗時列印的資訊']):斷言x是否None,是None則測試用例通過。
assertIsNotNone(x,[msg='測試失敗時列印的資訊']):斷言x是否None,不是None則測試用例通過。
assertIn(a,b,[msg='測試失敗時列印的資訊']):斷言a是否在b中,在b中則測試用例通過。
assertNotIn(a,b,[msg='測試失敗時列印的資訊']):斷言a是否在b中,不在b中則測試用例通過。
assertIsInstance(a,b,[msg='測試失敗時列印的資訊']):斷言a是是b的一個例項,是則測試用例通過。
assertNotIsInstance(a,b,[msg='測試失敗時列印的資訊']):斷言a是是b的一個例項,不是則測試用例通過。

class Test(unittest.TestCase):
      @classmethod
    def setUpClass(cls):
        print('測試開始啦...')

    @classmethod
    def tearDownClass(cls):
        print('測試結束啦...')

    def setUp(self):
        print('setUp...')

    def tearDown(self):
            print('setDown...')

      def test_testcase(self):
        self.assertEqual(1, 0)

1.3 testRunner 執行測試並輸出結果

直接執行測試用例,按照命名順序執行。
    unittest.main()

執行測試並在控制檯輸出測試結果:

    unittest.TextTestRunner(verbosity=2).run(testSuite)
    fileName = 'Report/Milito_Test'+str(time.time()).replace('.','')+'.html'
    f = open(fileName, 'wb')
    runner = HTMLTestReportCN.HTMLTestRunner(stream=f, title='測試報告', description='測試報告')
    runner.run(testSuite)
    f.close()

1.4 Skip 裝飾器

當執行用例時,有些用例如果不想執行,可用裝飾器暫時遮蔽該條測試用例。一種常見的用法就是比如說想除錯某一個測試用例,想先遮蔽其他用例就可以用裝飾器遮蔽。
@unittest.skip(reason): skip(reason)裝飾器:無條件跳過裝飾的測試,並說明跳過測試的原因。
@unittest.skipIf(reason): skipIf(condition,reason)裝飾器:條件為真時,跳過裝飾的測試,並說明跳過測試的原因。
@unittest.skipUnless(reason): skipUnless(condition,reason)裝飾器:條件為假時,跳過裝飾的測試,並說明跳過測試的原因。
@unittest.expectedFailure(): expectedFailure()測試標記為失敗。

2.將unitTest用於自動化測試

python可以編寫Web頁面和APP自動化測試指令碼[之前的文章],對於編寫的自動化測試指令碼進行以下操作,即可將unitTest用於自動化測試。

2.1 將自動化測試指令碼劃分為合適的用例,放在testCase之中。

2.2 每一個自動化測試指令碼的用例執行完之後,新增斷言,判斷測試是否成功。

2.3 每一個自動化測試指令碼本身可能存在一些問題,用try: *** except Exception as e: *** 丟擲異常,並在except中新增失敗的斷言。

2.4 如果自動化測試用例是否執行需要遵照某種規律,則設定變數進行標記,使用skip裝飾器對變數進行判斷,以跳過不執行的用例。

2.5 如果unitTest需要傳引數,則呼叫UnittestWithParam,並對unitTest+自動化測試 指令碼進行以下修改。

# -*- coding:utf-8 -*-
# UnittestWithParam.py

import unittest

class ParametrizedTestCase(unittest.TestCase):
    """ TestCase classes that want to be parametrized should
        inherit from this class.
    """

    def __init__(self, methodName='runTest', param=None):
        super(ParametrizedTestCase, self).__init__(methodName)
        self.param = param

    @staticmethod
    def parametrize(testcase_klass, param=None):
        """ Create a suite containing all tests taken from the given
            subclass, passing them the parameter 'param'.
        """
        testloader = unittest.TestLoader()
        testnames = testloader.getTestCaseNames(testcase_klass)
        suite = unittest.TestSuite()
        for name in testnames:
            suite.addTest(testcase_klass(name, param=param))
        return suite
# -*- coding:utf-8 -*-
import unittest
import HTMLTestReportCN

##用法-testcase
class TestOne(ParametrizedTestCase):
    def setUp(self):
        self.num = 9
        print("開始")

    def tearDown(self):
        print("完成")

    def test_something(self):
        self.assertEqual(self.param, self.num)

    def test_something_else(self):
        self.assertEqual(self.param, self.num)

##用法-測試
def main():
    suite = unittest.TestSuite()
    suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=None))
    suite.addTest(ParametrizedTestCase.parametrize(TestOne, param=13))

    # 控制檯輸出結果
    unittest.TextTestRunner(verbosity=2).run(suite)

    # 生成測試報告
    """
    fileName = 'unitTestParam.html'
    f = open(fileName, 'wb')
    runner = HTMLTestReportCN.HTMLTestRunner(stream=f, title='UT', description='測試報告')
    runner.run(suite)
    f.close()
    """

if __name__=="__main__":
    main()

3.總結

使用python+unitTest進行自動化測試,是對自動化測試指令碼進行更深度思考的機會,可以讓測試指令碼更接近高內聚低耦合的狀態,提升測試人員的工作效率。