華爲軟件編程規範學習(七)--可測性
轉自:http://blog.csdn.net/ce123_zhouwei/article/details/8887863
7-1:在同一項目組或產品組內,要有一套統一的爲集成測試與系統聯調準備的調測開關及相應打印函數,並且要有詳細的說明
說明:本規則是針對項目組或產品組的。
7-2:在同一項目組或產品組內,調測打印出的信息串的格式要有統一的形式。信息串中至少要有所在模塊名(或源文件名)及行號
說明:統一的調測信息格式便於集成測試。
7-3:編程的同時要爲單元測試選擇恰當的測試點,並仔細構造測試代碼、測試用例,同時給出明確的註釋說明。測試代碼部分應作爲(模塊中的)一個子模塊,以方便測試代碼在模塊中的安裝與拆卸(通過調測開關)
說明:爲單元測試而準備。
7-4:在進行集成測試/系統聯調之前,要構造好測試環境、測試項目及測試用例,同時仔細分析並優化測試用例,以提高測試效率
說明:好的測試用例應儘可能模擬出程序所遇到的邊界值、各種複雜環境及一些極端情況等。
7-5:使用斷言來發現軟件問題,提高代碼可測性
說明:斷言是對某種假設條件進行檢查(可理解爲若條件成立則無動作,否則應報告),它可以快速發現並定位軟件問題,同時對系統錯誤進行自動報警。斷言可以對在系統中隱藏很深,用其它手段極難發現的問題進行定位,從而縮短軟件問題定位時間,提高系統的可測性。實際應用時,可根據具體情況靈活地設計斷言。
示例:下面是C語言中的一個斷言,用宏來設計的。(其中NULL爲0L)
- #ifdef _EXAM_ASSERT_TEST_ // 若使用斷言測試
- void exam_assert(char * file_name, unsigned int line_no )
- {
- printf( "\n[EXAM]Assert failed: %s, line %u\n",
- file_name, line_no );
- abort();
- }
- #define EXAM_ASSERT( condition )
- if(condition) // 若條件成立,則無動作
- NULL;
- else // 否則報告
- exam_assert( __FILE__, __LINE__ )
- #else // 若不使用斷言測試
- #define EXAM_ASSERT(condition) NULL
- #endif /* end of ASSERT */
7-6:用斷言來檢查程序正常運行時不應發生但在調測時有可能發生的非法情況
7-7:不能用斷言來檢查最終產品肯定會出現且必須處理的錯誤情況
說明:斷言是用來處理不應該發生的錯誤情況的,對於可能會發生的且必須處理的情況要寫防錯程序,而不是斷言。如某模塊收到其它模塊或鏈路上的消息後,要對消息的合理性進行檢查,此過程爲正常的錯誤檢查,不能用斷言來實現。
7-8:對較複雜的斷言加上明確的註釋
說明:爲複雜的斷言加註釋,可澄清斷言含義並減少不必要的誤用。
7-9:用斷言確認函數的參數
示例:假設某函數參數中有一個指針,那麼使用指針前可對它檢查,如下。
- int exam_fun(unsigned char *str )
- {
- EXAM_ASSERT( str != NULL ); // 用斷言檢查“假設指針不爲空”這個條件
- ... //other program code
- }
7-10:用斷言保證沒有定義的特性或功能不被使用
示例:假設某通信模塊在設計時,準備提供“無連接”和“連接”這兩種業務。但當前的版本中僅實現了“無連接”業務,且在此版本的正式發行版中,用戶(上層模塊)不應產生“連接”業務的請求,那麼在測試時可用斷言檢查用戶是否使用“連接”業務。如下。
- #define EXAM_CONNECTIONLESS 0 // 無連接業務
- #define EXAM_CONNECTION 1 // 連接業務
- int msg_process(EXAM_MESSAGE *msg )
- {
- unsigned char service; /* message service class */
- EXAM_ASSERT( msg != NULL );
- service = get_msg_service_class( msg );
- EXAM_ASSERT( service != EXAM_CONNECTION ); // 假設不使用連接業務
- ... //other program code
- }
7-11:用斷言對程序開發環境(OS/Compiler/Hardware)的假設進行檢查
說明:程序運行時所需的軟硬件環境及配置要求,不能用斷言來檢查,而必須由一段專門代碼處理。用斷言僅可對程序開發環境中的假設及所配置的某版本軟硬件是否具有某種功能的假設進行檢查。如某網卡是否在系統運行環境中配置了,應由程序中正式代碼來檢查;而此網卡是否具有某設想的功能,則可由斷言來檢查。
對編譯器提供的功能及特性假設可用斷言檢查,原因是軟件最終產品(即運行代碼或機器碼)與編譯器已沒有任何直接關係,即軟件運行過程中(注意不是編譯過程中)不會也不應該對編譯器的功能提出任何需求。
示例:用斷言檢查編譯器的int型數據佔用的內存空間是否爲2,如下。
- EXAM_ASSERT( sizeof(int ) == 2 );
7-12:正式軟件產品中應把斷言及其它調測代碼去掉(即把有關的調測開關關掉)
說明:加快軟件運行速度。
7-13:在軟件系統中設置與取消有關測試手段,不能對軟件實現的功能等產生影響
說明:即有測試代碼的軟件和關掉測試代碼的軟件,在功能行爲上應一致。
7-14:用調測開關來切換軟件的DEBUG版和正式版,而不要同時存在正式版本和DEBUG版本的不同源文件,以減少維護的難度
7-15:軟件的DEBUG版本和發行版本應該統一維護,不允許分家,並且要時刻注意保證兩個版本在實現功能上的一致性
其他
7-1:在編寫代碼之前,應預先設計好程序調試與測試的方法和手段,並設計好各種調測開關及相應測試代碼如打印函數等
說明:程序的調試與測試是軟件生存週期中很重要的一個階段,如何對軟件進行較全面、高率的測試並儘可能地找出軟件中的錯誤就成爲很關鍵的問題。因此在編寫源代碼之前,除了要有一套比較完善的測試計劃外,還應設計出一系列代碼測試手段,爲單元測試、集成測試及系統聯調提供方便。
7-2:調測開關應分爲不同級別和類型
說明:調測開關的設置及分類應從以下幾方面考慮:針對模塊或系統某部分代碼的調測;針對模塊或系統某功能的調測;出於某種其它目的,如對性能、容量等的測試。這樣做便於軟件功能的調測,並且便於模塊的單元測試、系統聯調等。
7-3:編寫防錯程序,然後在處理錯誤之後可用斷言宣佈發生錯誤
示例:假如某模塊收到通信鏈路上的消息,則應對消息的合法性進行檢查,若消息類別不是通信協議中規定的,則應進行出錯處理,之後可用斷言報告,如下例。
- #ifdef _EXAM_ASSERT_TEST_ // 若使用斷言測試
- /* Notice: thisfunction does not call 'abort' to exit program */
- void assert_report(char * file_name, unsigned int line_no )
- {
- printf( "\n[EXAM]Error Report: %s, line %u\n",
- file_name, line_no );
- }
- #define ASSERT_REPORT( condition )
- if( condition ) // 若條件成立,則無動作
- NULL;
- else // 否則報告
- assert_report ( __FILE__, __LINE__ )
- #else // 若不使用斷言測試
- #define ASSERT_REPORT( condition ) NULL
- #endif /* end ofASSERT */
- int msg_handle(unsigned char msg_name, unsigned char * msg )
- {
- switch( msg_name )
- {
- case MSG_ONE:
- ... // 消息MSG_ONE處理
- return MSG_HANDLE_SUCCESS;
- ... // 其它合法消息處理
- default:
- ... // 消息出錯處理
- ASSERT_REPORT( FALSE ); // “合法”消息不成立,報告
- return MSG_HANDLE_ERROR;
- }
- }