天天看點

現代軟體工程講義 5.1 軟體的品質保證 (QA) 和測試 (Test)

在一個軟體團隊裡, 不同的人有不同程度的投入, 我們在 豬,雞和鹦鹉 的故事裡已經說明了. 不同的人還要在團隊中擔負不同的任務:

開發人員 (大部分内容在: 現代軟體工程講義 2 工程師的能力評估和發展)
項目經理 ( 内容在這裡)
測試人員 ( 本篇部落格 )

團隊中的管理人員/PM 負責分析市場, 設想功能, 定義使用者到底要什麼 – Why & What.

團隊中的開發人員/Dev 負責實作功能, 搞清楚怎麼才能滿足使用者的需求 – How.

團隊中的測試人員/QA 搞清楚我們的軟體是否滿足了使用者的需求 – Whether.

最後所有成員一塊決定産品是否能釋出, 什麼時候能釋出 – When.  

測試/Test 和 品質保障/QA (Quality Assurance) 這兩個詞經常混用, 這兩個概念是完全同等, 還是隻是有一部分交集, 還是是另一個的真子集, 衆說紛纭, 在各自的語境中, 都有意義。對于《現代軟體工程》的語境,  我們這樣規定:

QA: 運用各種手段, 在軟體工程的各個階段確定軟體的品質能幫助軟體團隊實作目标。

Test (測試) : 特指驗證代碼的行為是否符合功能規格說明書 (spec) 的規定。

在這樣的定義下, Test隻是 QA 工作的一部分。

對測試工作的種種誤解

一些人對“測試”這一工作還有很多誤, 解例如下面的似是而非的觀點:

1) 測試在項目的最後進行就可以了。

這是遠遠不夠的。當你在項目後期發現了問題,問題的根源往往是項目早期的一些決定和設計,這時候,再要對其進行修改就比較困難了。這要求測試人員從項目開始就要積極介入,從源頭防止問題的發生。有人會說,我是一個小小的測試人員,項目開始的時候我能做什麼?這就是小小測試人員努力的方向。

2) 測試就得根據規格說明書(spec)來測,是以是很機械的。

那不一定,即使你的軟體産品功能100% 符合spec 的要求,但是使用者也可能非常恨你的軟體。這時,測試人員就沒有盡到責任,因為測試人員要從使用者的角度出發,測試軟體。

3) 測試人員當然也寫代碼,但是品質不一定要很高。

開發人員的代碼沒寫好,可以依賴于測試人員來發現問題。但是如果測試人員的代碼沒寫好,我們依賴誰來測試和改錯呢?這就要求我們測試人員的代碼品質特别高,因為我們是最後一道防線,如果我們的代碼和測試工作有漏洞,那麼Bug就會跑到使用者那裡去。

4) 測試隻是被動地接受别人的産出, 然後開始自己的工作, 比較被動, 不能發揮創造性。

也許狹義定義下的 測試用例 是要等開發人員的代碼, 然後開始測試。 但是整個品質保證工作(QA)需要前瞻性, 主動性, 創造性的工作。Weinberg 說過: “也許沒有任何一項測試技術比前瞻性更有價值” (Probably no single  testing technique is of more value than foresight.) [1]

各種測試方法

現代軟體工程講義 5.1 軟體的品質保證 (QA) 和測試 (Test)

(注意到上圖的黑箱子和白箱子了麼? 它們裡面裝的都是測試的寶貝)

[下面的解釋大部分來自于  《移山之道》 ]

7.1  基本名詞解釋及分類

統一思想要從基本名詞解釋開始。

1.Bug:缺陷軟體的缺陷

Bug可以分為這三個組成部分:症狀(Symptom)、程式錯誤(Fault)、根本原因(Root cause)。

(1)Symptom:即從使用者的角度看,軟體出了什麼問題。

例如,在輸入(3 2 1 1)的時候,程式錯誤退出。

(2)Fault:即從代碼的角度看,代碼的什麼錯誤導緻了軟體的問題。

例如,代碼在輸入為某種情況下通路了非法的記憶體位址——0X0000000C。

(3)Root Cause:錯誤根源,即導緻代碼錯誤的根本原因。

例如,代碼對于id1==id2的情況沒有做正确判斷,進而引用了未賦初值的變量,産生了以上的情況。

以下是一個完整的例子。

(1)Symptom:使用者報告,一個Windows應用程式有時會在啟動時報錯,程式不能運作。

(2)Fault:有時候一個子視窗的handle為空,導緻程式通路了非法記憶體位址,此為代碼錯誤。

(3)RootCause:代碼并沒有確定建立子視窗(在CreateSubWindow()内部才做)發生在調用子視窗之前(在OnDraw()時調用),是以子視窗的變量有時會在通路時為空,導緻上面提到的代碼錯誤。

2.Test Case:測試用例

測試用例描述了一個完整的測試過程,包括測試環境、輸入、期望的結果等。

3.Test Suite:測試用例集合

即一組相關的測試用例。

提示:Suite發音念作“sweet”,不是念作“suit”,一大半的學生都念錯。

7.1.1  從測試設計的方法分類

測試設計有兩類方法:Black box(黑箱)、White box(白箱)。

這是每個接觸過軟體測試的人都會給出的答案。但這隻是整個軟體測試的入門知識。可以跳過去,直接讨論下面的内容。

問:我在網上看到有人争論黑箱測試和白箱測試哪一個是另一個的基礎,還有哪一個更難,哪一個更有前途,等等。據說河曲數位在搞“灰箱測試”,是不是更進階?能不能簡單講一講?

阿超:大家都有這些問題麼?

雜曰:[略去對此問題熱烈的争論500字]

阿超:聽了大家的争論,看來我們的确得花不少時間統一認識。

所謂黑箱/白箱,是指軟體測試設計的方法,不是軟體測試的方法!注意“設計”二字。

黑箱:在設計測試的過程中,把軟體系統當作一個“黑箱”,無法了解或使用系統的内部結構及知識。一個更準确的說法是“Behavioral Test Design”,從軟體的行為,而不是内部結構出發來設計測試。

白箱:在設計測試的過程中,設計者可以“看到”軟體系統的内部結構,并且使用軟體的内部知識來指導測試資料及方法的選擇。“白箱”并不是一個精确的說法,因為把箱子塗成白色,同樣也看不見箱子裡的東西。有人建議用“玻璃箱”來表示。

在實際工作中,我們不應畫地為牢,嚴格隻用某一種方法來設計測試方法。在實際的測試中,當然是對系統了解得越多越好。所謂“灰箱”的提法,正是這一反映。有些測試專家甚至希望我們忘記全部的“箱子”和它們的顔色。

問:如果我是一個開發者,我能做“黑箱”麼?

答:并不是要禁止懂得程式内部結構的人員來進行黑箱測試設計,隻不過是在設計時有意不考慮軟體的内部結構。例如:在測試程式内部基本子產品的時候(單元測試),通常要求由對程式結構非常了解的程式員來設計,這是因為内部子產品的“行為”和程式的外部功能并沒有直接的關系,而且内部基本子產品的“行為”通常沒有明确的定義。另一個例子是“易用性測試”,在設計此類測試的時候,沒必要糾纏于程式的内部結構,而是着重于軟體的界面和行為。但是軟體易用性測試也需要很多專業知識。這也從一個側面表明“黑箱”和“白箱”沒有簡單的高低之分。

一旦測試用例寫出來之後,大可以忘了它們是從哪種顔色的箱子裡出來的,用它就可以了。

問:有人說“黑箱”,有人說“黑盒”,到底是“箱子”還是“盒子”?

答:在網上搜尋了一下,“黑箱測試”有超過100萬個記錄,“黑盒測試”隻有70多萬。是以“箱子”赢了。

問:但是我聽九條說他剛進公司實習的時候隻能做“黑箱測試”,這是什麼意思?

九條:我剛到公司實習的時候,兩眼一摸黑,看到啥都是“黑箱”,即使測試用例是由懂得程式結構的開發人員寫出來的,我還是隻會機械地運作。我是知其然,不知其是以然,箱子當然是黑的。後來看得多了,學了一些東西,能夠了解程式的結構和算法,箱子的顔色就變淺了,好像能看到箱子裡的東西一樣。

7.1.2  從測試的目的分類

1.功能測試

以下的測試術語主要是測試軟體的功能。在表7-1所列的測試中,測試的範圍由小到大,測試者也由内到外——從程式開發人員(單元測試)到測試人員,到一般使用者(Alpha/Beta測試)。

表7-1  功能測試分類

測試名稱 測試内容
Unit Test 單元測試——在最低的功能/參數上驗證程式的正确性
Functional Test 功能測試——驗證子產品的功能
Integration Test 內建測試——驗證幾個互相有依賴關系的子產品的功能
Scenario Test 場景測試——驗證幾個子產品是否能夠完成一個使用者場景
System Test 系統測試——對于整個系統功能的測試
Alpha/Beta Test 外部軟體測試人員(Alpha/Beta測試員)在實際使用者環境中對軟體進行全面的測試

2.非功能測試

一個軟體除了基本功能之外,還有很多功能之外的特性,這些叫“non-functional requirement”,或者“quality of service requirement”——服務品質需求。沒有軟體的功能,這些特性都無從表現出來,是以,我們要在軟體開發的适當階段——基本功能完成後做這些測試。

如表7-2所示:

表7-2  非功能測試

Stress/load test 測試軟體在負載情況下能否正常工作
Performance test 測試軟體的效能
Accessibility test 可通路性測試——測試軟體是否向殘疾使用者提供足夠的輔助功能
Localization/Globalization Test 本地化/全球化測試
Compatibility Test 相容性測試
Configuration Test 配置測試——測試軟體在各種配置下能否正常工作
Usability Test 易用性測試——測試軟體是否好用
Security Test 軟體安全性測試

7.1.3  按測試的時機和作用分類

在開發軟體的過程中,不少測試起着“烽火台”的作用,它們告訴我們軟體開發的流程是否順暢,這些測試如表7-3所示:

表7-3  烽火台

Smoke Test “冒煙”——如果測試不通過,則不能進行下一步工作
Build Verification Test 驗證建構是否通過基本測試
Acceptance Test 驗收測試,為了全面考核某方面功能/特性而做的測試

另一些測試名稱,則是說明不同的測試方法,如表7-4所示:

表7-4  不同測試方法

Regression Test “回歸”測試——對一個新的版本,重新運作以往的測試用例,看看新版本和已知的版本相比是否有“退化”(Regression)
Ad hoc (Exploratory) Test 随機進行的、探索性的測試
Bug Bash Bug大掃蕩——全體成員參加的找“小強”活動
Buddy Test 夥伴測試——測試人員為開發人員(夥伴)的特定子產品作的測試

7.2  單元測試(Unit Test)

二柱:我們也試過用單元測試來保證品質,要求每人都要寫,在簽入代碼前必須通過單元測試。但是搞了幾個星期就不了了之。

大家七嘴八舌地列舉了單元測試的問題:

◆  有時單元測試報了錯,再運作一次就好了,後來大家就不想花時間改錯,多運作幾次,有一次通過就行了;

◆  單元測試中好多錯都和環境有關,在别人的機器都運作不成功;

◆  花在單元測試上的時間要比寫代碼的時間還多,提高代碼覆寫率到90%以上太難了;

◆  單元測試中我們還要測試效能和壓力,花了很多時間;

◆  我們都這麼費勁地測了,那還要測試人員幹什麼?

阿超:看來問題還不少,我們留到後面再談(見後面“單元測試”的具體描述)。

7.3  代碼覆寫率測試(Code Coverage Analysis)

前面單元測試中提到代碼覆寫率,簡單來說代碼被執行過,就是“覆寫過”,如果一段程式運作了一組測試用例之後,100%的代碼被執行了,那麼是否就說明再也不用寫新的測試用例了呢?

答案是否定的。

(1)不同代碼是否執行,有很多組合,一行代碼被執行過,沒有問題,并不表明這一行程式在所有可能條件的組合下都能正确無誤地運作。

(2)代碼覆寫不能測出還沒有寫的代碼(缺少的邏輯)導緻的錯誤。比如:

a. 沒有檢查過程調用的傳回值;

b. 沒有釋放資源。

繼續閱讀