嵌入式軟件,有必要進行自測嗎?

04/02 09:50
810
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

大家好,我是雜燴君。

本次我們來介紹嵌入式可測試軟件設計。

什么是可測試性?就是你這個軟件模塊/函數(shù)接口寫完之后,可以較為方便、較為全面地進行自測 。

作為嵌入式軟件開發(fā)者,我們在開發(fā)自己負責的模塊之前,大家事先會做什么?

在公司沒有規(guī)定要寫文檔的情況下,可能我們很多人會直接開干、寫代碼。

一些對自己模塊比較負責的人,會寫設計文檔,用于評審或者供給其他同事看。

我個人覺得,在寫代碼之前,除了寫設計文檔,還有一點很重要:思考我們的模塊如何進行自測。

軟件迭代,大多公司的過程如下:

軟件工程師開發(fā) -> 釋放版本 -> 測試工程師測試 -> 軟件工程師修bug -> 釋放版本 -> ...

每次發(fā)現(xiàn)一個bug,這個bug修復的周期會很長。

所以,我們盡可能地在釋放給測試之前,進行一個完整的自測,減少一些不必要的bug產(chǎn)生(主路徑bug)。

增加一個步驟:

軟件工程師開發(fā) ->?軟件工程師自測?-> 釋放版本 -> 測試工程師測試 -> 軟件工程師修bug -> 釋放版本 -> ...

軟件工程師自測,這個在我們嵌入式行業(yè),很多大公司可能會作為一個標準的流程。但是在一些中小公司,可能會忽略這個步驟,那這就靠我們自覺了。因為進行充分的自測,受益的也是我們,免去了后面反復地被bug修復打斷我們的需求開發(fā)。

其實,我們自己模塊的開發(fā),除了供給測試工程師測試之外。有時候,我們也會供給我們的團隊成員調用,或是其他部門的同事使用,我們在交付出去進行聯(lián)調之前,需要保證質量,也能免去后面很多的聯(lián)調成本。

建議大家,寫代碼之前,寫個文檔,里面包含:

    自測的思考設計思路

并且自測的思考放在設計之前。需要先思考如何自測,因為在思考自測的時候,會對我們的設計也是有幫助的。

舉個簡單的例子來認識可測試性程序。

有一個計算函數(shù)cal_func,其計算依賴于存在flash里的數(shù)據(jù)a,與一個外部輸入的數(shù)據(jù)b。

此時,有如下兩種實現(xiàn)方法:

方法一:

int?get_a_from_flash(void)
{
int?a =?0;
?flash_read(&a,?sizeof(int));

return?a;
}

int?cal_func(int?b)
{
int?res =?0;
int?a = get_a_from_flash();

?res = a + b;

return?res;
}

// 調用
cal_func(5);

方法二:

int?get_a_from_flash(void)
{
int?a =?0;
?flash_read(&a,?sizeof(int));

return?a;
}

int?cal_func(int?a,?int?b)
{
int?res =?0;

?res = a + b;

return?res;
}

// 調用
cal_func(get_a_from_flash(),?5);

這種類似場景,實際開發(fā)中應該有不少,大家平時都是按照方式一寫代碼還是方式二寫代碼呢?

從可測試性的角度來看,?方法二的實現(xiàn),更具備可測試性?。

我們寫完代碼,一般為了保證質量我們要進行充分的測試。

方式一,因為有一個數(shù)據(jù)是在函數(shù)內部從flash中讀取的,所以這個數(shù)據(jù)我們不太方便進行控制,而能控制的只有參數(shù)b。那么,這樣子,我們在調用測試時,測得就不是很全,也不能靈活地控制測試路徑。

方式二,計算所依賴的數(shù)據(jù)都通過函數(shù)參數(shù)留出來了,我們可以很方便地對函數(shù)進行測試,可以很方便地輸入不同的數(shù)據(jù)組合。

并且,一般地,我們會引入一些?單元測試框架?,用來統(tǒng)一管理我們的測試例子。

嵌入式中,常用的測試框架:

    Unity:https://github.com/ThrowTheSwitch/Unity/releasescutest:https://sourceforge.net/projects/cutest/embunit :https://sourceforge.net/projects/embunitgoogletest:https://github.com/google/googletest/releases

使用測試框架之后,針對cal_func函數(shù)設計的測試代碼如:

int?ut_cal_func(int?argc,?char?*argv[])
{
? ??if?(argc !=?3)
? ? {
? ? ? ??printf("Param num errn");
? ? ? ??return?USAGE;
? ? }

? ??// 預期結果
? ??int?expected_res = atoi(argv[2]);?
? ??// 實際結果 ? ? ? ? ? ? ? ? ?
int?res = cal_func(atoi(argv[0]), atoi(argv[1])); ??

? ??if?(expected_res == res)
? ? {
? ? ? ??printf("input %d, %d, test pass!n", atoi(argv[0]), atoi(argv[1]));
? ? }
? ??else
? ? {
? ? ? ??printf("input %d, %d, test failed!n", atoi(argv[0]), atoi(argv[1]));
? ? }

return0;
}

我們封裝成串口測試指令:

// 測試路徑1
ut app ut_cal_func?1?2?3
? ??
// 測試路徑2
ut app ut_cal_func?2?3?5
? ??
// ...

輸出:

input 1, 2,?test?pass!
input 2, 3,?test?pass!

這就是一個可測試性軟件設計的一個小例子,通過這個小例子大家應該認識到可測試性軟件的好處了吧?

所以,之后寫代碼,寫之前,有必要先想清楚,這個模塊最后要怎么進行自測?要測哪些地方?

設計的軟件可測試性強,我們就能在開發(fā)階段進行充分地測試,在開發(fā)階段盡可能多地解決一些邏輯上的問題,從而保證更高質量地軟件交付。

以上就是本次的分享,歡迎收藏、轉發(fā)!

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

本公眾號專注于嵌入式技術,包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學習筆記,同時,公眾號內包含大量的學習資源。歡迎關注,一同交流學習,共同進步!