2013年10月27日 星期日

Round 7: Testing improves design

U步驟:

在測試議題上,根據Round 6回顧,列出問題如下:
SP6:建立vector與matrix輸出的單元測試。
SP7:建立vector與matrix超限功能與測試。

讓我們先解決SP6。vector物件的輸出函數在實作上讀取u的分量,適當的符號裝飾,直接使用C++ 輸出物件 cout 進行輸出:


void outputVector(vector u){
cout << "[";
for (int i=1; i<u.dim(); ++i)
cout << u[i] << ",";
cout << u[u.dim()] << "]" << endl;
return;
}

我們的問題是如何測試?前次L步驟說不該直接讓cout輸出「污染」測試輸出畫面,所以不能直接在測試中呼叫 outputVector。

結論:outputVector的可測試性(testability)不佳。SP6的目標就是改善outputVector與outputMatrix的可測試性。

D步驟:

如何改善outputVector的testability?解決方法之一,是以間接的方式測試:先讓vector u轉成一個可測試且容易輸出到cout的中間表示型式(intermediate form),再將該型式輸出到cout。假設後者均能以C++內建的方式做到,則能測試vector u轉出的中間表示型式,即能測試outputVector!

有了這個解決方案,接下來就是決定vector u轉出的中間表示型式。由於outputVector輸出是給使用者看的,直覺上字串(string)就是一個適用的中間表示型式。

列出待辦工作如下:

T23 測試 vector轉成字串。
T24 撰寫vector轉成字串的函數。
T25 修改 outputVector。
T26 迴歸測試。
T27 測試 matrix轉成字串。
T28 撰寫 matrix轉成字串的函數。
T29 修改 outputMatrix
T30 迴歸測試。

相信你已經知道如何列出這些工作了,同時這些工作已經難不倒你了!

C步驟:

完成T23、T24、T25的相關程式片段如下。
(學習課題:string, ostringstream)

T23:
TEST (outputVector, vector){

double a[3]={1,2,3};

vector u(3,a);

CHECK(string("[1,2,3]")==u.string()); }

T24:in vector.h

class vector {

...

public:
...
std::string string() const;
};

in vector.cpp

string vector::string() const {

ostringstream oss;

oss << "[";
for (int i=1; i<= dim()-1; ++i)
oss << (*this)[i] << ",";
oss << (*this)[dim()] << "]";
return oss.str();
}

T25:
void outputVector(vector u){
cout << u.string() << endl;
return;
}


T25得到的 outputVector 對當前程式功能似乎夠了,但稍加思考,不難發現它有些限制,例如輸出兩個向量

vector u(...);
vector v(...);
outputVector(u);
outputVector(v);

後二行code看起來有些小題大作。為什麼不寫成

cout << u << "\n" << v << endl; // u v 間有換行
或者
cout << u << " " << v << endl; // u v 間無換行

這看起來是個好想法,而且並不難做到,我只要 overload operator << 即可:

ostream & operator << (ostream & os, const vector & u){
return os << u.string();
}

同意嗎?matrix相關工作請自己試試看,可參考我寫的程式

L步驟:

此round我們出發時,面對的是一個測試的問題。不容易測試的函數,通常隱含著其他的問題。工作T24完成後,outputVector函數變得可測;T25完成後,你可以將 vector透過標準的operator << 輸出到 cout以外的輸出串流(output stream),如檔案(使用ofstream)、字串(使用ostringstream)等。此時outputVector即無存在的必要!故有本篇的title: 

Testing improves design.

此外,我可以說

Design to enable testing. 

© Y C Cheng, 2013. All rights reserved.

沒有留言:

張貼留言