摘要:本文是作者的一堂實際課程的教學案例,通過檢查學生作業的形式,引出本堂課的講授內容。隨著對作業中問題的層層提問與解決,引出軟件測試概念,并把軟件測試思想融合到程序語言的設計過程中,旨在培養學生在初學程序語言設計時就養成良好的編程習慣,建立軟件測試的思想。
關鍵詞:軟件測試;C語言;測試用例;語法錯誤;邏輯錯誤
中圖分類號:G642文獻標識碼:B
文章編號:1672-5913 (2007) 20-0106-04
1教學目標
1. 通過教師的啟發引導,使學生理解軟件測試的基本概念;
2 通過對程序案例的過程講解,使學生掌握基本控制語句switch、break的使用;
3. 通過對程序案例的錯誤排除,讓學生了解語法錯誤和邏輯錯誤的概念;
4. 了解軟件測試在程序中的作用。
2教學重點及難點
1 軟件測試思想的建立;
2 使學生養成良好的編程習慣;
3教學過程
3.1以點帶線,導出概念
(課件:請大家查閱書籍和網上搜索,了解軟件錯誤給我們帶來的危害。)
師:這是我們上次課后給同學們布置的作業,讓大家通過查閱書籍和網上搜索,給出這問題的解釋。現在請同學們舉手發言。
生1:1996年6月4日,阿麗亞娜5型火箭第一次鑒定發射,因火箭導航電腦軟件系統發生故障而失敗;
生2:2003年4月,一個軟件故障因為有些機票的價格被誤定為1.86美元而導致美國航空集團公司損失數千美元;
生3:2003年5月4日,俄羅斯“聯盟—TMA1”載人飛船返回地球途中,由于飛船的導航計算機軟件設計中的錯誤引起飛船偏離了降落目標地點約460公里;
生4:2004年12月21日,美國空軍一架F/A-22“猛禽”戰斗機進行戰術和訓練工作時墜毀。飛行員安全彈射,飛機墜毀,事故與飛機的飛行控制軟件有關;
生5:美國商務部的國立標準技術研究所(NIST:National Institute of Standards and Technology)有關軟件缺陷的損失調查報告表示,“據推測,由于軟件缺陷而引起的損失額每年高達595億美元。這一數字相當于美國國內生產總值的0.6%”。
師:通過剛才大家的踴躍發言,老師了解到大家在課后都做了很充分的準備。如此看來,軟件設計中的錯誤給我們帶來的危害是相當沉重的。那么,如何去規避這些錯誤的發生?如何去發現這個錯誤?這就是軟件工程中的軟件測試思想。請同學們總結一下,軟件測試具體做什么工作?
生:找出軟件中的錯誤。
師:軟件測試就是找出軟件中存在的問題,我們把軟件中存在的問題稱為缺陷(bugs)。如何查找這些缺陷?
(設計思路:問題是最好的老師,是學生學習的引導者,沒有問題便沒有深入。在教學中,我們經常發現學生問不出問題,其原因在于學生沒能消化知識,不能靈活運用。因此教師在教學過程中,應當有意設置一些問題,引導學生在問題的解決過程中學習,即提出問題,留給學生時間思考、討論、解決問題。在這個環節中,將問題以課后作業的形式布置下去,啟發引領學生充分利用網上資源和圖書館資源查閱信息,使學生養成自學與分析問題的能力,逐層導出軟件測試的概念,為軟件測試方法的引入進行鋪墊。通過課堂提問,活躍了課堂氣氛,使學生在輕松愉悅的環境中學習。)
3.2引用案例,明確概念,步步遞進,解決問題
(課件:問題描述)用C語言程序完成如下功能:輸入某年某月某日,判斷這一天是這一年的第幾天。(學生通過網絡將作業提交給老師,老師審閱后,發現學生作業中存在的問題)
師:這是上次課后布置的作業。
師:現將一個學生作業做為本次課程的教學案例。請同學們看屏幕。
(教師進入Turbo C for windows 集成實驗與學習環境,展示學生編寫的程序結構,邊操作邊演示)
程序內容如下:
main()
{
int day,month,year,sum,leap;
printf(\"\please input year,month,day\\");
scanf(\"%d,%d,%d\",year,month,day);
switch(month)
/*先計算某月以前月份的總天數*/
{
case 1:sum=0;
case 2:sum=31;
case 3:sum=59;
case 4:sum=90;
case 5:sum=120;
case 6:sum=151;
case 7:sum=181;
case 8:sum=212;
case 9:sum=243;
case 10:sum=273;
case 11:sum=304;
case 12:sum=334;
default:printf(\"data error\");
}
sum=sum+day;/*再加上某天的天數*/
printf(\"It is the %dth day.\",sum);}
師:請同學根據這個程序,說出該程序的設計思想。
生:要判斷輸入日期在一年中的第幾天,首先要計算此日期前的月份包含多少天,以3月5日為例,應該先把前兩個月的加起來,然后再加上5天即本年的第幾天。
師:第一步,看一下這個程序的結構是否合理。
首先,大家知道在編寫程序時,遇到具有按不同情況分轉的多路問題,一般采用C語言提供的if-else-if的嵌套結構和開關語句來實現。這里雖可用嵌套if-else-if語句來實現,但if-else-if語句使用不方便,并且容易出錯。針對本案例,多分支的入口執行語句因具有規律性,可按輸入的月份進行選擇執行,因此選擇開關語句結構解決該問題是適合的。
師:(接下來復習switch開關語句)。
執行switch開關語句時,是將變量逐個與case后的常量進行比較,若與其中一個相等,則執行該常量下的語句,若不與任何一個常量相等,則執行default后面的語句。
師:第二步,我們運行程序,檢查程序的正確性。
(多媒體機房演示,將程序運行結果投影在大屏幕上)
運行程序,輸入測試用例:2007,3,8
運行結果如圖1所示。

師:請同學們注意,程序運行的結果與實際問題的結果是否一致?
生:不一致。不應該是342天。
師:該問題出現的原因是缺少了break語句。
師:(接下來復習break開關語句)。
break語句通常用在循環語句和開關語句中。當break用于開關語句switch中時,可使得程序在執行完選中的分支后,跳出整個switch語句(即跳到switch接的一對{}之后),完成switch。如果沒有這個break,程序將在繼續前進到下一分支,直到遇到后面的break或者switch完成。
下面請同學們對上面的程序進行改進。
生:(在計算機上改進原程序)
改進后的程序如下:
main()
{
int day,month,year,sum,leap;
printf(\"\please input year,month,day\\");
scanf(\"%d,%d,%d\",year,month,day);
switch(month)
/*先計算某月以前月份的總天數*/
{
case 1:sum=0;break;
case 2:sum=31;break;
case 3:sum=59;break;
case 4:sum=90;break;
case 5:sum=120;break;
case 6:sum=151;break;
case 7:sum=181;break;
case 8:sum=212;break;
case 9:sum=243;break;
case 10:sum=273;break;
case 11:sum=304;break;
case 12:sum=334;break;
default:printf(\"data error\"); break;
}
sum=sum+day; /*再加上某天的天數*/
printf(\"It is the %dth day.\",sum);}
師:下面我們對剛才改進的程序來運行一下。
運行程序,輸入測試用例:2007,3,8
程序運行結果如圖2所示。

生1:這次程序運行結果是正確的。
生2:如果是閏年呢?比如我們輸入:2000,3,8,結果會是什么呢?
師:我們可以進一步測試一下。
運行程序,輸入測試用例:2000,3,8
程序運行結果如圖3所示。

生:這次的結果是不正確的。
師:由此看來,上次對程序的改進仍是不完善的。請同學們思考一下,如何進一步改進這個程序?
生:對于這個案例,如果是閏年且輸入月份大于3時需考慮多加一天,那么此程序還要根據輸入的年份判斷是否為閏年。閏年的判斷規則為:如果此年份能被400整除,則是閏年;如果此年份能被4整除,而不能被100整除,則是閏年;否則不是。
師:請同學們根據剛才這位同學的思想,對程序做進一步修改。
生:(在計算機上改進原程序)
改進后的程序如下:
#include
void main()
{
int day,month,year,sum,leap;
printf(\"\please input year,month,day\\");
scanf(\"%d,%d,%d\",year,month,day);
switch(month) /*先計算某月以前月份的總天數*/
{
case 1:sum=0;break;
case 2:sum=31;break;
case 3:sum=59;break;
case 4:sum=90;break;
case 5:sum=120;break;
case 6:sum=151;break;
case 7:sum=181;break;
case 8:sum=212;break;
case 9:sum=243;break;
case 10:sum=273;break;
case 11:sum=304;break;
case 12:sum=334;break;
default:printf(\"data error\");break;
}
sum=sum+day;/*再加上某天的天數*/
if(year%400 = = 0||(year%4 = = 0year%100!=0))/*判斷是不是閏年*/
leap=1;
else
leap=0;
if(leap = = 1month>2) /*如果是閏年且月份大于2,總天數應該加一天*/
sum++;
printf(\"It is the %dth day.\",sum);}
師:運行修改后的程序;
輸入測試用例:2000,3,8
運行結果如圖4所示。

生:這次程序運行結果與實際是一致的。
師:經過對上面的案例分析,結合以前我們學習過的知識,我們將C程序的錯誤可以分為兩種:語法錯誤和邏輯錯誤
(1) 語法錯誤
這是C語言初學者出現最多的錯誤,比如,分號“;”是每個C語句的結束的標志,在C語句后忘記寫“;”就是語法錯誤。發生語法錯誤的程序,編譯是通不過的,用戶須通過軟件的提示信息來修改。
(2) 邏輯錯誤
邏輯錯誤就是用戶編寫的程序已經沒有語法錯誤,可以運行,但得不到所期望的結果(或正確的結果),也就是說由于程序設計者的原因,程序并沒有按照程序設計者的思路來運行。比如我們這堂課的例子就是這樣:我們的目的是求輸入某年某月某日,判斷這一天是這一年的第幾天。但由于沒有考慮到對輸入年份進行是否為閏年的判斷,就是導致運行結果的錯誤。象這種情況這就是邏輯錯誤。
編譯軟件對有邏輯錯誤的程序是發現不了,要用戶不斷輸入測試數據、跟蹤程序的運行過程才能發現程序中的邏輯錯誤,這是最不容易修改的。比如軟件的BUG就是邏輯錯誤,發行補丁程序就是修改邏輯錯誤;如大家最常見的就是Windows操作系統經常發布的補丁程序了。在這節課,我們通過學生案例,將軟件測試思想運用到了程序設計當中,是想讓同學們在開始學習程序設計語言時,就養成良好的編程習慣,規范編程思想,善于用軟件測試的方法去調試和修改自己的程序。
(設計思路:教學是一門藝術,更是教師的創造性、能動性和教學水平的綜合體現,在教學過程中要將學生的積極性和潛能充分發揮出來,這樣才能達到最佳的教學效果。通過引用學生作業,讓學生不斷地對案例進行修正,將軟件測試思想融入到程序設計當中。一方面,對激發學生求知欲望和創造性思維,對提高學生的程序設計能力和水平具有積極的作用;在遵循以人為本的素質教育理念指導下,讓教師成為學生獲取綜合知識的引導者,成為學生自主學習的指導者,成為學生創造能力的培育者;另一方面,通過對案例的分析與講解,強化了軟件工程中的軟件測試理論,為學生后續課的學習進行了鋪墊。)
4回顧總結,強化認知
師:通過本節課的學習,大家學到了什么?
生1:軟件測試思想的建立。
生2:軟件測試的測試方法。
生3:在復習與鞏固C語言知識的同時,了解了編程過程中測試的重要性。知道了在程序開發的過程中,測試是一個不可缺少的重要環節。
師:同學們總結的非常好。通過今天的學習,我們知道了“三分編程七分測試”,說明程序測試的工作量要比編程大得多。
測試程序是一個艱苦、心細、又有技巧的事,只有經常上機多調試程序,才能不斷地積累經驗、提高程序調試技能。
一個優秀的程序員是在改進自己所編寫程序的過程中,不斷地積累經驗、逐步完善,并走向成功的。請同學們記住:只在岸邊看而不下水的人是永遠學不會游泳的。要想達到賣油翁的“油自錢孔入而錢不濕”的高超技巧,必須多測試程序,這樣才能成為一名優秀的程序員。
作者簡介
張輝(1970-),女,陜西省華縣人,講師,本科,研究方向:軟件技術、網絡技術
通信地址:河南省開封市東京大道西段黃河水利職業技術學院信息工程系,475003
電話:13849128689
E-mail:kfzhanghui@163.com
基金項目:國家示范性高等職業院校建設項目06-14
河南省教育科學“十一五”規劃課題 課題編號:2006-JKGHAG-189