1. 程式人生 > >unittest框架學習,一步步生成html格式測試報告

unittest框架學習,一步步生成html格式測試報告

主要參考文章:
https://blog.csdn.net/xiaoquantouer/article/details/75089200
unittest中最核心的四部分是:
1.test fixture(測試韌體)
2.test case(測試用例)
3.test suite(測試套件)
4.test runner(測試執行器 )

1.測試韌體(test fixture):
一個測試用例環境的搭建和銷燬,是一個fixture。
包括兩部分setUp()和tearDown()
執行測試程式碼之前的準備部分和測試結束之後的清掃程式碼
(這裡舉例以下,例如要測試百度搜索selenium這個場景,我們的測試韌體可以這樣寫,setUp()裡寫開啟瀏覽器,瀏覽器最大化,和開啟百度首頁等指令碼程式碼;在tearDown()裡寫結束搜尋後,退出並關閉瀏覽器的程式碼。)

2.測試用例(test case):
什麼是測試用例呢?就是一個完整的測試流程,包括測試前準備環境的搭建(setUp),執行測試程式碼(run),以及測試後環境的還原(tearDown)。
一個測試用例中,包括測試韌體,但測試韌體可以不寫,但是至少有一個已test開頭的函式。unittest會自動化識別test開頭的函式是測試程式碼,如果你寫的函式不是test開頭,unittest是不會執行這個函式裡面的指令碼的,這個千萬要記住,所有的測試函式都要test開頭,記住是小寫的哦

3.測試套件 (test suite):
多個測試用例集合在一起,就是TestSuite,而且TestSuite也可以巢狀TestSuite。
如果測試用例比作單個學生,測試套件就是好像是班級的概念。

4.測試執行器 (test runner):
test runner是一個用來執行載入測試用例,並執行用例,且提供測試輸出的一個組建。test runner可以載入test case或者test suite進行執行測試任務。其中的run(test)會執行TestSuite/TestCase中的run(result)方法

5.TestLoader:
TestLoader是用來載入TestCase到TestSuite中的,其中有幾個loadTestsFrom__()方法,就是從各個地方尋找TestCase,建立它們的例項,然後add到TestSuite中,再返回一個TestSuite例項。

6.TextTestResult:


測試的結果會儲存到TextTestResult例項中,包括運行了多少測試用例,成功了多少,失敗了多少等資訊。

unittest的流程:
1.寫好TestCase
2.由TestLoader載入TestCase到TestSuite
3.由TextTestRunner來執行TestSuite
(我們通過命令列或者unittest.main()執行時,main會呼叫TextTestRunner中的run來執行,或者我們可以直接通過TextTestRunner來執行用例。)
4.執行的結果儲存在TextTestResult中

注:
verbosity引數可以控制執行結果的輸出,0 是簡單報告、1 是一般報告、2 是詳細報告。
用 setUp()、tearDown()、setUpClass()以及 tearDownClass()可以在用例執行前佈置環境,以及在用例執行後清理環境
我們可以通過skip,skipIf,skipUnless裝飾器跳過某個case,或者用TestCase.skipTest方法。
使用unittest編寫用例,必須遵守以下規則:
1.測試檔案必須先import unittest
在這裡插入圖片描述
2.測試類必須繼承unittest.TestCase
在這裡插入圖片描述
3.測試方法必須以“test_”開頭
在這裡插入圖片描述
4.測試類必須要有unittest.main()方法
在這裡插入圖片描述

先寫了一個待測試檔案mathfunc.py內容如下:

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
def add(a,b):
    return a+b
def minus(a,b):
    return a-b
def multi(a,b):
    return a*b
def divide(a,b):
    return a/b

接下來寫了一個它的測試用例,新建了一個test_mathfunc.py,內容如下:(注意四個規則)

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import unittest
from mathfunc import *

class TestMathFunc(unittest.TestCase):
    def test_add(self):
        self.assertEqual(3,add(1,2))
        self.assertNotEqual(3,add(2,2))
    def test_minus(self):
        self.assertEqual(1,minus(3,2))
    def test_multi(self):
        self.assertEqual(6,multi(2,3))
    def test_divide(self):
        self.assertEqual(2,divide(6,3))
        self.assertEqual(2.5,divide(6,3))

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

另一個測試用例test_mathfuna.py
前邊沒有用到,後邊呼叫兩個用例的時候才用到了

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import unittest
from mathfunc import *

class TestMathFuna(unittest.TestCase):
    def test_multi(self):
        self.assertEqual(6,multi(2,3))
    def test_minus(self):
        self.assertEqual(1,minus(3,2))
    def test_divide(self):
        self.assertEqual(2,divide(6,3))
    @unittest.skip("i don't want to run this case.")
    def test_minus(self):
        self.assertEqual(1, minus(3, 2))
if __name__== '__main__':
    unittest.main(verbosity=2)

執行單個測試方法:
呼叫test_mathfunc.py的測試方法,能執行test_mathfunc.py裡的test_minus、test_add和test_divide

test_suit.py

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc#匯入test_mathfunc裡的TestMathFunc類

if __name__=='__main__':
    suite=unittest.TestSuite()

    tests=[TestMathFunc("test_minus"),TestMathFunc("test_add"),TestMathFunc("test_divide")]
    suite.addTests(tests)

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

執行單個測試方法或整個測試類
1.直接用addTest方法新增單個TestCase
2.用addTests + TestLoader新增整個測試類

TestLoader:
loadTestsFromName()
loadTestsFromTestCase()
test_suit1.py

import unittest
from test_mathfunc import TestMathFunc

if __name__=='__main__':
    suite = unittest.TestSuite()
    
    # 直接用addTest方法新增單個TestCase
    suite.addTest(TestMathFunc("test_multi"))

    # 用addTests + TestLoader
    # loadTestsFromName(),傳入'模組名.TestCase名'
    suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
    suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc']))  # loadTestsFromNames(),類似,傳入列表

    # loadTestsFromTestCase(),傳入TestCase
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
    
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

在專案中生成一個文字的測試報告
test_suit2.py

# -*- coding: utf-8 -*-

import unittest
from test_mathfunc import TestMathFunc

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))

    with open('UnittestTextReport.txt', 'a') as f:
        runner = unittest.TextTestRunner(stream=f, verbosity=2)
        runner.run(suite)

又寫了一個test_mathfuna來測試兩個用例的呼叫
test_suittwo.py

import unittest
from test_mathfunc import TestMathFunc
from test_mathfuna import TestMathFuna
if __name__=='__main__':
    suite = unittest.TestSuite()
    # 用addTests + TestLoader
    # loadTestsFromName(),傳入'模組名.TestCase名'
    suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
    suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfuna.TestMathFuna'))

    with open('UnittestTextReporttwo.txt', 'a') as f:
        runner = unittest.TextTestRunner(stream=f, verbosity=2)
        runner.run(suite)

test_suittwo1.py

# -*- coding:utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc
from test_mathfuna import TestMathFuna

if __name__=='__main__':
    suite=unittest.TestSuite()

    tests=[TestMathFunc("test_minus"),TestMathFunc("test_add"),TestMathFunc("test_divide")]
    tests1=[TestMathFuna("test_divide")]
    suite.addTests(tests)
    suite.addTests(tests1)

    with open('UnittestTextReporttwo2.txt', 'a') as f:
        runner = unittest.TextTestRunner(stream=f, verbosity=2)
        runner.run(suite)

生成html格式的測試報告
test_suit Open Html.py

# coding=utf-8

import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':
    suite = unittest.TestSuite()

    tests = [TestMathFunc("test_add"), TestMathFunc("test_minus"), TestMathFunc("test_divide")]
    suite.addTests(tests)

    with open('HTMLReport1.html', 'wb+') as f:
        runner = HTMLTestRunner(stream=f,
                                title='MathFunc Test Report',
                                description='generated by HTMLTestRunner.',
                                verbosity=2
                                )
        runner.run(suite)

這裡遇到了一個問題:python3 引入HTMLTestRunner執行 報錯 ImportError: No module named ‘StringIO’
這個我在個人分類的使用appium中遇到的問題中有寫:
https://blog.csdn.net/weixin_40412060/article/details/82841473