大學終于要邁入尾聲了,工作也找到了相對較好的,現在就差畢業設計了。我一直堅信着這樣的原則:當面臨很多選擇時,選擇最難的那一個,是以我選擇了室内導盲系統設計。其實這也不是最難的,隻是我以前沒有做過類似的工作,其他多多少少都有涉及,是以特地選擇了這個。
說難其實也不難,因為硬體已經做好了,我要做的就是設計軟體。軟體設計的方法有很多種,還是秉持着那條原則:選擇最難的那個,是以我選擇了測試驅動開發的方式。
在寫這篇文章的時候,我的室友打機打得正酣,而我則在一邊忙着敲代碼,這時突然意識到,為啥他們能夠接受那樣低水準的工作而沒有任何抱怨,甚至在當初連做選擇都沒有就接受了,然後就一直拼命的打機消磨時光,除了一個一出生就是官二代,富二代之外,其他還是必須要找工作,并且一找到工作就馬上接受,哪怕這份工作的待遇非常低。原因非常簡單:見識的局限性。我已經出來實習工作了,見識到公司裡有些人也是這樣的四個字:混吃等死。當我意識到這點的時候,是渾身打顫:為啥有些人以後的發展是那樣子,有些人以後是這樣子,除開一些無法改變的原因之外,最根本的就是他們骨子裡就接受了這樣的事實:我就是隻能找到這樣的工作,這樣的工作已經很好了。這就是所謂的認命。
明白到這點之後,我更加慶幸自己當初在找到第一份工作的時候還是有繼續找,直到找到一家在該行業也算是巨頭的公司并且通過他們的面試。就算自己現在的技術水準很菜,就算自己現在寫的代碼還是很爛,但我們還是要一直堅持在最前線,一直向上,也許,在前方,就有不一樣的風景在等着我們。
所謂的測試驅動開發思想非常簡單,就是在編寫具體的代碼前,先編寫測試代碼,然後想辦法讓自己的代碼通過測試。思想非常簡單,但實作起來卻不容易,除開工具,就是自己所寫的測試單元可以說是基于自己的想象,因為沒有任何具體的實作,隻有測試用例。有具體的輸入輸出的測試用例還是比較好寫,但如果是更加抽象的測試用例,該測試什麼都是個問題。但這并不阻止我去編寫測試單元,因為我深深明白到一件事:人之是以選擇混吃等死,是因為他們根本就不知道在這上面的風景到底是怎樣。是以,故意去使用一些進階的技術并不是壞事,它會讓我們明白到原來還有這樣的東西,就算嘗試是失敗的,但至少我們也明白到這東西大概是什麼樣子的,并且在這個嘗試中學到很多東西。
第一個測試子產品就是測試手機發送連接配接指令還有接收響應指令。
指令的格式已經是固定的,是以這不是難事,第一個測試可以這樣測試:
public void test{
byte[] byteArr = {};
byte[] command = mCommand.getCommand();
for(int i = 0, length = byteArr.length; i < length; ++i){
assertEquals(byteArr[i], command[i]);
}
}
為了讓這個測試通過,我們必須建立一個類Command:
public class Command{
private byte[] mCommandByte = {};
public byte[] getCommand(){
return mCommandByte;
}
}
第一個測試通過!在通過這個測試的時候,我們建立了一個用于存儲指令的類Command,它的第一個職責就是傳回相關的指令。
我們接着編寫測試單元。
發送指令是向整個區域網路所有可能的網關發送,每發送完一條,指令的序号就會加1,等到99後又從0開始。根據這樣的特性,我們可以這樣寫測試:
public void test(){
Gateway gate = new Gateway();
List<byte[]> commandList = new ArrayList<byte[]>();
for(int i = 0; i < 100; ++i){
byte[] command = {(byte)i, ...};
commandList.add(command);
}
commandList.add(new byte[]{(byte)0, ...});
for(int i = 0; i < 101; ++i){
byte[] response = mCommand.send(gate);
byte[] bytes = bytesList.get(i);
assertEquals(bytes[0], response[0]);
}
}
這裡涉及到新的對象:網關Gate,是以需要建立一個新的類:Gataway。Gateway在接收到Command發送的指令後,會傳回一條響應指令,該指令的序号和接收到的指令是一樣的。
public class Gateway {
private byte[] RESPONSE_COMMAND = {};
public byte[] response(byte[] command) {
RESPONSE_COMMAND[0] = command[0];
return RESPONSE_COMMAND;
}
這裡Command多了一個新的職責:send():
public byte[] send(Gateway gate) {
byte[] response = gate.response(CONNECT_COMMAND);
CONNECT_COMMAND[0]++;
if (CONNECT_COMMAND[0] > (byte) 99) {
CONNECT_COMMAND[0] = (byte) 0;
}
return response;
}
就是這樣,我們簡單的通過兩個測試就建立了兩個基本的類型:Command和Gateway,并且确定了它們的基本行為,當然,在随後更多的測試中,這兩個類會添加更多測試,甚至是被證明是無用的而被删除掉,都有可能。
測試驅動開發就是利用預先編寫好的測試代碼驗證自己編寫de代碼是否正确,如果不符合測試,說明代碼存在問題,必須修改直到測試通過。當然,這種方式要求我們一開始編寫的測試代碼必須是正确的,這比編寫代碼需要更多的經驗和技術要求,幸好,測試代碼也是可以修改的,隻要驗證測試代碼不符合目前所有測試的用例情況,這個在嘗試各種努力仍無法讓測試通過時,可以考慮下測試的正确性。