天天看點

c語言ut測試白盒測試方法,白盒測試

測試理論回顧:

黑盒測試:是針對整個産品系統進行的測試,驗證系統是否滿足需求規格的定義,及軟體産品的正确性和性能等是否滿足其需求規格的要求。

灰盒測試:是介于白盒測試與黑盒測試之間的一種測試,灰盒測試多用于內建測試階段,不僅關注輸出、輸入的正确性,同時也關注程式内部的情況。

白盒測試:是通過程式的源代碼進行測試而不使用使用者界面。這種類型的測試需要從代碼内部在算法,路徑,條件等等中的缺點或者錯誤,進而加以修正。

單元測試:

單元測試是針對程式的最小單元來進行正确性檢驗的過程。單元:一個單元可能是單個程式、類、對象、方法(函數)等。 優點是可以減少BUG;快速定位BUG;提高代碼品質;減少調試時間。缺點是周期時間長;耗費資源(主要是人力資源);能力要求高。

一、單元測試流程

1. 單元測試-計劃:1) 确定要測試代碼範圍;2) 評估标準(确定被測代碼的覆寫率)

2. 測試政策-設計:1) 拿到開發代碼進行調整(保證單元間可獨立執行)

3. 測試政策-實作:1) 根據調整好的代碼-畫流程圖;2) 根據流程圖畫流圖-确定複雜度、路徑;3) 根據複雜度和路徑确定測試用例(測試資料)

4. 單元測試-執行:1) 使用測試架構(UnitTest)編寫單元測試用例;2) 測試用例(代碼)和測試資料分離;3) 生成測試報告

二、單元測試-計劃

确定要測試代碼以及确定這些被測代碼的評估标準、優先級等說明:1. 确定單元測試範圍(哪些代碼要做單元測試);評估标準-(被測代碼的邏輯覆寫率)

1.1、如何确定20%代碼

确定單元測試的代碼測試範圍,我們依據:二八原則(20%的代碼中隐藏了80%的缺陷)

1. 頻率:使用頻率高的代碼段;

2. 複用性:(是否已被複用,是否被别的地方引用,如果被别的地方調用這個函數,沒問題,基本不用測)

1). 全新(指沒有被複用的代碼)

2). 部分複用

3). 全部複用

3. 開發人員:

1). 技術(指由技術水準不那麼高的開發人員寫的代碼)

2). 業務(指由對業務不那麼熟悉的開發人員寫的代碼)

4. 複雜度:業務邏輯複雜度(一般認為圈複雜度在7級以上代碼包括在20%的代碼中)

最後,我們會得到一張表,來列名我們要測的代碼範圍:

c語言ut測試白盒測試方法,白盒測試

測試範圍

1.2、評估标準(覆寫率)如何确定邏輯覆寫率

例如,我們拿到一段代碼,實作的一個需求,我們首先要畫流程圖(使用統一規定标準圖形,描述程式運作的具體步驟),然後以此來确定覆寫率,并且以後可以根據流程圖畫流圖    1. 語句覆寫率,說明:非分支非判斷的代碼,覆寫率計算方式:被覆寫語句/總語句,例如,流程圖裡有3個語句,對于一個測試資料,它能覆寫2個語句,則語句覆寫率為2/3

2. 分支覆寫率,說明:判斷語句的分支,例如if判斷有兩個分支,覆寫率計算方式:覆寫分支/總分支數,例如流程圖裡的if判斷有2個分支,對于一個測試資料,它能覆寫1個分支,則分支覆寫率為1/2

3. 條件覆寫率,說明:一個條件有兩個結果 true、false,是以一個條件分母為2,兩個條件分母為4...例如:if username=='admin' and pwd=='123456':這裡就有兩個條件,分母為4

注意:條件之間使用邏輯符 and連接配接,第一個條件如果失敗,不會在去判斷第二個條件,如果測試資料是username==ad, pwd就不會判斷,覆寫率為1/4;如果為or第一個條件失敗回去判斷第二條件

4. 路徑覆寫率,說明:路徑就是從開始-到結束的過程, 覆寫率計算方式:覆寫路徑/全部路徑

注意:路徑的分子永遠為1, 有時候看流程圖路徑有4條,但有一條永遠不可成立,是以實際路徑為3條,計算路徑覆寫率時分母就為3

5. 分支條件覆寫率,說明:分支和條件的組合,1.分子=分支覆寫率的分子+條件覆寫率的分子;2.分母=分支覆寫率的分母+條件覆寫率的分母

三、單元測試政策-設計

單元測試政策:針對單元測試選擇測試的一種方式;

單元測試政策方式:

1. 自上到下,方式:從最上層函數往下開始逐層測試,缺點(成本高)

2. 自下到上,方式:從最底層函數往上開始逐層測試,缺點(周期長,需要開發寫完所有代碼才能開始測試)

3. 孤立政策【推薦使用】方式:選擇需要進行測試的函數進行測試,優點:選擇重要的代碼進行測試,測試構成中免不了測的某些函數會調用别的函數,是以一定要學會打樁

注意:打樁-->打樁就是模拟編寫一個我們需要引用的函數,模拟定義被調用的函數名,提示:一般我們隻模拟寫個函數名,直接傳回相應的結果即可(return 結果;pass)

示例:def fun_1(self):

return true

四、單元測試政策-實作

測試政策實作:把我們標明的代碼,而且保證標明的代碼能獨立運作(已經打完樁),轉向流程圖、流圖及用例的過程

測試政策實作如何操作:1. 将測試代碼轉換成流程圖;2. 根據流程圖轉換為流圖,有了流圖測試用例就出來了

c語言ut測試白盒測試方法,白盒測試

流程圖

什麼是流圖?

概念:表達程式業務邏輯的複雜度一種示意圖

構成:

1) 圈:判斷條件(一個條件一個圈)、語句塊(一條或多條語句,挨着的語句可以用一個圈表示)兩者都圈

2) 線:箭頭指向的線,用來連接配接圈和圈的指向

流圖的目的:

1) 确定單元的複雜度級别

2) 确定測試用例

備注: 路徑的個數為複雜度的級别(一條路徑為1個複雜度級别),有N個條件最少有N條路徑,最多N+1條路徑

c語言ut測試白盒測試方法,白盒測試

流圖

* 路徑:2 (1-2-3,1-3);複雜度:2;用例個數:2

c語言ut測試白盒測試方法,白盒測試

根據流圖寫的測試用例

五、單元測試——執行

通過單元測試架構對要進行測試代碼的實踐過程需求:通過Python語言編寫一個運算的類(Calc),類中包含兩個函數:add(self,a,b) 傳回a+b之和;sub(self,a,c) 傳回a-c之差

- 導包 UnitTest 、Calc類

- 建立單元測試類 Test01(內建 unitTest.TestCase)

- 建立testAdd()函數

- 導入Calc類中的add函數

- 添加斷言

- 建立testSub()函數

- 導入Calc類中的sub函數

- 添加斷言

- 執行測試:unittest.main()import unittest

# 導入要測試的 Calc類

from UT.Day02.Code.test01_lx01import Calc

class Test_Calc(unittest.TestCase):

def setUp(self):

print("setUp被執行")

def tearDown(self):

print("tearDown被執行")

def test_add(self):

result=Calc().add(10,10)

print("test_add方法被執行")

self.assertEqual(result,20)

def test_sub(self):

result=Calc().sub(10,20)

print("test_sub方法被執行")

self.assertEqual(result,-10)

if __name__== '__main__':

# main運作目前類中所有test開頭的方法

unittest.main()

資料直接寫入代碼中,如果數量龐大,我們需要頻繁改動資料或複制備援代碼進行實作資料測試目的。做不到資料分離(代碼和資料分開),不便維護

參數化

根據需求動态擷取資料并進行指派的過程

參數化方式:XML格式(1); CSV格式(2);JSON串 (3);TXT文本(4)

提示:括号内為推薦使用優先級,從小到大;1-2為擴充了解,3-4建議重點了解

XML格式:

XML是一種标記語句,很類似HTML标記語言;字尾 .xml;XML是傳輸和存儲資料,焦點在資料;HTML是顯示資料,焦點在外觀;XML不适合大量參數化資料時使用XML格式:

單元測試

XST

2008

39.95

1. 必須有XML聲明語句:<?xml version="1.0" encoding="UTF-8"?>

2. 必須要有一個根元素,如:

3. 标簽大小寫敏感

4. 屬性值用雙引号

5. 标簽成對

6. 元素正确嵌套

7. 标簽名可随意命名,但有以下限制(注意:命名允許重複)

1) 不能以數字或者标點符号開始參

2)不能以字元 “xml”(或者 XML、Xml)開始

3) 名稱不能包含空格需求:對三角形案例單元測試使用XML格式進行參數化

被測代碼段:

class Sjx(): def sjx(self,a,b,c):

# 判斷是否為三角形

if a+b>c and a+c>b and b+c>a:

# 判斷是否為等邊三角形

if a==b and b==c:

return "等邊三角形"

elif a==b or a==c or b==c:

return "等腰三角形"

else:

return "普通三角形"

else:

return "不是三角形"

if __name__ == '__main__':

print(Sjx().sjx(2,3,4))

--------------------------------------------------------------------------------------------------------------------------

操作步驟:1. 編寫XML資料檔案;2. 編寫讀取XML子產品函數;3. 單元測試子產品中引用XML讀取函數;4. 執行

編寫XML資料檔案:

2

3

4

普通三角形

2

2

2

等邊三角形

2

2

3

等腰三角形

2

3

2

等腰三角形

3

2

2

等腰三角形

3

2

1

不是三角形

1

2

3

不是三角形

2

3

1

不是三角形

編寫讀取XML子產品函數# 導包

minidomfrom xml.dom import minidom

class Read_Xml():

def readXml(self,node,num,nodeChild):

# 解析xml文檔

dom=minidom.parse("../DataPool/sjx.xml")

# 擷取文檔對象

root=dom.documentElement

# 擷取bian元素

element=root.getElementsByTagName(node)[int(num)]

# 擷取指定bian元素 如b1

return element.getElementsByTagName(nodeChild)[0].firstChild.data

def get_len(self,node):

# 解析xml文檔

dom=minidom.parse("../DataPool/sjx.xml")

# 擷取文檔對象

root=dom.documentElement

# 擷取bian元素

return len(root.getElementsByTagName(node))

if __name__ == '__main__':

print(Read_Xml().readXml("bian",0,"b3"))

print(Read_Xml().get_len("bian"))

單元測試子產品中引用XML讀取函數;執行# 導包 unittest、三角形函數、讀取xml資料類

import unittest

from UT.Day02.Code.sjx import Sjx

from UT.Day02.ReadData.read_xml import Read_Xml

# 執行個體化三角形

sjxClass=Sjx()

# 執行個體化讀取xml類

readXmlClass=Read_Xml()

class Test_Xml(unittest.TestCase):

def test001(self):

for i in range(readXmlClass.get_len("bian")):

# 目的測試三角形程式

result=sjxClass.sjx(int(readXmlClass.readXml("bian",i,"b1")),                                             int(readXmlClass.readXml("bian", i, "b2")),                                                                                int(readXmlClass.readXml("bian", i, "b3")))

# 添加斷言,判斷三角形程式傳回的結果是否符合我們預期結果             self.assertEqual(result,readXmlClass.readXml("bian", i, "expect"))             print(readXmlClass.readXml("bian",i,"b1"), readXmlClass.readXml("bian", i, "b2"),                     readXmlClass.readXml("bian", i, "b3"), readXmlClass.readXml("bian", i,                     "expect"),"--》驗證通過")

重點分析:

1. 導入XML包 from xml.dom import minidom

2. 加載解析 dom=minidom.parse(filename)

3. 擷取對象  root=dom.documentElement

4. 擷取子元素 aas=root.getElementsByTagName(one)[0]

5. 擷取子元素值 aas.getElementsByTagName(two)[0].firstChild.data

CSV格式:

CSV是一種以逗号做分割的表格格式; 字尾 .csv使用CSV實作三角形案例參數化-操作步驟

1. 建立CSV檔案

2. 編寫CSV讀取子產品函數

3. 單元測試-引用CSV讀取函數

4. 執行

建立CSV檔案:

2,2,2,等邊三角形2,2,3,等腰三角形2,3,2,等腰三角形3,2,2,等腰三角形1,2,3,不是三角形2,3,1,不是三角形3,2,1,不是三角形2,3,4,普通三角形

編寫CSV讀取子產品函數:

# 導包

import csv

class Read_Csv():

def readCsv(self):

# 打開csv

with open("../DataPool/sjx.csv","r",encoding='utf-8') as f:

datas=csv.reader(f)

# 建立空清單,把單行傳回的清單添加成整體的清單

lines=[]

for data in datas:

# 添加數組

lines.append(data)

return lines

if __name__ == '__main__':

print(Read_Csv().readCsv())

單元測試-引用CSV讀取函數;執行:

# 導入unittest、三角形函數、csv讀取參數類

import unittest

from UT.Day02.Code.sjx import Sjx

from UT.Day02.ReadData.read_csv import Read_Csv

# 執行個體化三角形

sjxClass=Sjx()

# 執行個體化讀取csv工具

readCsvClass=Read_Csv()

class Test_Csv(unittest.TestCase):

# 測試三角形函數程式

def test001(self):

for i in range(len(readCsvClass.readCsv())):             result=sjxClass.sjx(int(readCsvClass.readCsv()[i][0]),

int(readCsvClass.readCsv()[i][1]),

int(readCsvClass.readCsv()[i][2]))

# 斷言:三角新運作完後傳回的結果和預期結果做對比             self.assertEqual(result,readCsvClass.readCsv()[i][3])

print(readCsvClass.readCsv()[i][0], readCsvClass.readCsv()[i][1],                     readCsvClass.readCsv()[i][2], readCsvClass.readCsv()[i][3],"---》驗證通過")

if __name__ == '__main__':

unittest.main()

重點分析:

1. 導包 import csv

2. 打開csv檔案:

with open("../Data/sjx.csv","r",encoding="utf-8") as f:

lines=csv.reader(f)

JSON串:

一種輕量級資料交換格式;字尾名 .json ;提示: 接口測試一般使用JSON為接口傳遞資料規範格式

格式:{"name":"張三","age":28};提示:由鍵值對組成,健名和值之間使用分号(:)分割,多個鍵值對之間使用逗号(,)分割使用JSON實作三角形案例參數化-操作步驟

1. 編寫JSON檔案

2. 編寫JSON讀取子產品函數

3. 單元測試-引用JSON讀取函數

4. 執行

編寫JSON檔案 :

{"data": [ {"b1":2,"b2":2,"b3":2,"expect":"等邊三角形"}, {"b1":2,"b2":2,"b3":3,"expect":"等腰三角形"}, {"b1":2,"b2":3,"b3":2,"expect":"等腰三角形"} ]}

編寫JSON讀取子產品函數 :# 導包 json

import json

# 打開檔案流

class Read_Json():

def readJson(self):

with open("../DataPool/sjx.json","r",encoding="utf-8") as f:

# 調用load()

datas=json.load(f)

# 傳回字典data鍵名對應的值

return datas["data"]

if __name__ == '__main__':

print(Read_Json().readJson())

單元測試-引用JSON讀取函數;執行 :# 導包 unittest 、三角形函數程式、讀取json類

import unittest

from UT.Day02.Code.sjx import Sjx

from UT.Day02.ReadData.read_json import Read_Json

# 執行個體化三角形

sjxClass=Sjx()

# 執行個體化讀取JSON類

readJsonClass=Read_Json()

class Test_Json(unittest.TestCase):

# 測試三角形

def test001(self):

for i in range(len(readJsonClass.readJson())):

# 調用三角形函數

result=sjxClass.sjx(int(readJsonClass.readJson()[i]["b1"]),                                                                                       int(readJsonClass.readJson()[i]["b2"]),                                                                                       int(readJsonClass.readJson()[i]["b3"]))

# 斷言 三角形傳回的結果是否與預期結果相符             self.assertEqual(result,readJsonClass.readJson()[i]["expect"])

# 列印運作參數及結果

print(readJsonClass.readJson()[i]["b1"], readJsonClass.readJson()[i]["b2"],                     readJsonClass.readJson()[i]["b3"], readJsonClass.readJson()[i]["expect"],"--->                        通過!")

if __name__ == '__main__':

unittest.main()

難點分析

1. 導入JSON包(import JSON)

2. 打開JSON檔案并解析

with open('../DataXML/sjx.json','r',encoding='utf-8') as f:

file=json.load(f)

TXT文本:

一種純文字格式; 字尾名 .txt;TXT文本優點: 編寫測試資料友善;使用子產品函數讀取時便捷使用TXT實作三角形案例參數化-操作步驟

1. 建立txt文本并寫入測試資料

2. 編寫讀取txt子產品函數

3. 單元測試-引用JSON讀取函數

4. 執行

建立txt文本并寫入測試資料:第一條邊,第二條邊,第三條邊,預期結果

2,2,2,等邊三角形

2,2,3,等腰三角形

2,3,2,等腰三角形

3,2,2,等腰三角形

1,2,3,不是三角形

2,3,1,不是三角形

3,2,1,不是三角形

2,3,4,普通三角形

編寫讀取txt子產品函數 :class Read_Txt():

def readTxt(self):

# 打開txt檔案流

with open("../DataPool/sjx.txt","r",encoding="utf-8") as f:

# 通過檔案流調用讀取的方法讀取資料--->所有行

datas=f.readlines()

# 建立清單 --》添加分割後的單行清單資料

lines=[]

# 周遊

for data in datas:

'''

strip():去除字元串前後回車,空格,tab鍵

split():使用指定符号進行分割字元串并以清單格式傳回分割後的資料

'''

# 把分割後的單行清單資料添加到整體的列中,并傳回

lines.append(data.strip().split(","))

# 傳回資料 [1:] 傳回從下标1開始傳回資料

return lines[1:]

'''

f.read() #讀取所有資料

f.readline() # 讀取單行

f.readlines() # 讀取所有行

'''

if __name__ == '__main__':

print(Read_Txt().readTxt())

單元測試-引用JSON讀取函數;執行 :# 導包 unittest、三角形、txt讀取

import unittest

from UT.Day02.Code.sjx import Sjx

from UT.Day02.ReadData.read_txt import Read_Txt

# 執行個體化三角形

sjxClass=Sjx()

# 執行個體化txt

readTxtClass=Read_Txt()

class Test_Txt(unittest.TestCase):

# 測試三角形程式

def test001(self):

for i in range(len(readTxtClass.readTxt())):

# 調用三角形方法

result=sjxClass.sjx(int(readTxtClass.readTxt()[i][0]),

int(readTxtClass.readTxt()[i][1]),

int(readTxtClass.readTxt()[i][2]))

# 調用斷言,判斷三角形程式執行後的結果是否與預期結果相符

self.assertEqual(result,readTxtClass.readTxt()[i][3])

# 為了檢視友善,我把執行成功後的資料列印一下

print(readTxtClass.readTxt()[i][0], readTxtClass.readTxt()[i][1],                     readTxtClass.readTxt()[i][2], readTxtClass.readTxt()[i][3],"-->通過!")

if __name__ == '__main__':

unittest.main()

難點分析:導包:不需要讀取方法:readlines()

1. 如何讀取txt文本?

with open(r'../DataXML/三角形.txt','r',encoding='utf-8') as f:

2. 如何去除行尾/n換行符?

line.strip()

c語言ut測試白盒測試方法,白盒測試

單元測試總結

--------------------------------------------------------------------------------

HTML報告生成

如何生成HTML報告?導入HTML報告模闆模闆:HTMLTestRunner.py編寫生成HTML子產品

# 導入unittest包

import unittest

# 導入 HTMLTestRunner模闆包

from UnitTest.Day02.ReadData.HTMLTestRunner import HTMLTestRunner

#導入時間包

import time

# 定義測試子產品路徑

dirpath='.'

discorver=unittest.defaultTestLoader.discover(dirpath,pattern='test*.py')

if __name__=='__main__':

#存放報告的檔案夾

report_dir='../TestReport'

#報告名稱含時間,時間格式

now=time.strftime("%Y-%m-%d %H_%M_%S")

#報告完整路徑+名稱

report_name=report_dir+'/'+now+'result.html'

#打開報告寫入結果

with open(report_name,'wb')as f:

runner=HTMLTestRunner(stream=f,title="UnitTest Report-SJX",description='Test Case Report')

runner.run(disconver)