繼上篇 [解鎖新姿式] 兄dei,你代碼須要優化了 介紹一些代碼的優化的小技巧
。java
可是咱們除了在代碼編寫上須要優雅
, 還須要編寫對應的測試用例
, 以此來保證代碼的質量。git
在這篇咱們繼續在學習
如何編寫有保證質量
的代碼。github
在剛剛學習編程的時候,因爲沒有接觸過單元測試/TDD
相關知識, 只是知道有這麼回事,不覺得然。致使工做的時候,拿到一個新需求,只知道埋頭苦寫
。會出現如下場景:編程
產品:增長一個新功能 blalala.
我:好的沒問題,一個星期擼出來
一個月後.......
我:個人接口寫好了!能夠測試了。
測試:你本身測過沒 ??
我:放心postman
測過了,穩的一批。(/滑稽)
一分鐘後.......
測試:你的接口又雙叕 報500
了 (黑人問號??) 我:不可能!確定是你的問題api
一次偶然的機會,接觸到 TDD
開發模式,今後打開新的世界。原來編程還能夠這麼玩 : )框架
TDD是測試驅動開發
(Test-Driven Development)的英文簡稱, 是敏捷開發
中的一項核心實踐
和技術,也是一種設計方法論。TDD的原理是在開發功能代碼以前,先編寫單元測試
用例代碼,測試代碼肯定須要編寫什麼產品代碼。post
說白了,就是開發功能代碼以前,先編寫
測試用例
代碼`單元測試
咱們先來看一個「經典」
的 TDD 問題,入手學習 TDD 開發
,感覺 TDD 開發的魅力所在學習
編寫一個程序,打印出從1到100的數字,將其中3的倍數替換成「Fizz」
,5的倍數替換成「Buzz」
。既能被3整除、又能被5整除的數則替換成「FizzBuzz」
。以下圖所示 測試
在動手寫代碼以前,咱們要首先弄清需求的範圍
和優先級
,例如給出的FizzBuzz
需求,1-100
就是範圍
,對應優先級是1
,肯定了需求的範圍和優先級後,而後咱們就能夠開始coding
~
咱們首先新建一個FizzBuzz測試類
public class FizzBuzzTest {
@Test
void show_raw_number(){
FizzBuzz fizzbuzz = new FizzBuzz(1);
assertThat(fizzbuzz.getResult()).isEqualTo("1");
}
}
public class FizzBuzz {
public FizzBuzz(int input) {
}
public String getResult() {
return "";
}
}
複製代碼
舒適提示:
- 測試類推薦使用
駝峯式
命名,測試方法 推薦使用下劃線
命名- 這裏我使用的是
AssertJ
單元測試框架,這款框架主要亮點之一是支持鏈式
調用。assertThat
方法是org.assertj.core.api.Assertions.assertThat
包靜態
方法.- assertThat(A).isEqualTo(B),意思是
斷言
(預測) A 等於 B,若是 A == B的話,返回True
表示經過
測試用例,不然False
,表示測試失敗,不經過。- 更多的使用方法能夠參考AssertJ 官方網站
咱們先建立一個 FizzBuzz
類, 建立 getResult()
方法,空實現, 傳入參數 1
,斷言(預期)fizzbuzz 輸出結果是 1
,先運行測試用例,會出現以下效果
小夥伴:你會不會寫啊,這麼簡單的還用測試?還報錯!!
彆着急,測試驅動開發,講究是的按部就班的節奏
聽個人,往下看 相信你會get
到feel
:)
看到紅燈
程序提示,咱們預期結果(Expected
)是 「1」
, 但實際結果(Actual
)是0
,說明咱們的程序有錯。
接下來咱們進一步來修改咱們的測試用例,以此來經過測試用例。 修改以下:
public String getResult() {
return "1";
}
複製代碼
而後再次運行咱們的測試用例
舒適提示:
編寫剛恰好經過測試用例的代碼。
此次「完美」
經過測試!而後咱們開始編寫下一個測試用例~
完美?? 黑人問號?? 拿刀哪一個,先把刀放下 你聽我說。
咱們來測試 第一種狀況,將其中3的倍數替換成「Fizz」
,編寫 3
的測試用例
@Test
public void show_fizz(){
FizzBuzz fizzBuzz = new FizzBuzz(3);
assertThat(fizzBuzz.getResult()).isEqualTo("Fizz");
}
複製代碼
建立一個show_fizz
方法, 此次輸入參數爲 3,而後繼續運行測試用例
「紅燈報錯」
,而後我能夠繼續修改咱們的
getResult
方法 以此來經過測試用例。
public String getResult() {
if (input % 3 == 0){
return "Fizz";
}
return String.valueOf(input);
}
複製代碼
而後再次運行測試用例~
綠色!!經過測試!
看到這裏,咱們能夠發現一個規律
紅燈行,綠燈停
當測試用例是「紅燈」
時,咱們就應該動手編寫出,能經過測試的測試用例。
當測試用例是「綠燈」
時,咱們就應該停下來思考,下一個測試用例改如何編寫。
咱們繼續小步前進,繼續編寫第二種狀況,5的倍數替換成「Buzz」
, 編寫 入參 5
的測試用例
@Test
public void show_buzz(){
FizzBuzz fizzBuzz = new FizzBuzz(5);
assertThat(fizzBuzz.getResult()).isEqualTo("Buzz");
}
複製代碼
不出意外的話,是 紅燈
咱們繼續修改getResult()
方法,以此來經過測試用例。
public String getResult() {
if (input % 3 == 0){
return "Fizz";
}
// 新增
if (input % 5 == 0){
return "Buzz";
}
return String.valueOf(input);
}
複製代碼
而後繼續運行測試用例,綠燈經過~
咱們繼續小步前進,考慮第三種狀況,既能被3整除
、又能被5整除
的數則替換成「FizzBuzz」
,編寫 入參 15
的測試用例
@Test
public void show_fizz_buzz(){
FizzBuzz fizzBuzz = new FizzBuzz(15);
assertThat(fizzBuzz.getResult()).isEqualTo("FizzBuzz");
}
複製代碼
這裏相信你們能猜到結果,紅燈
,這裏我就演示結果了。而後咱們修改對應 getResult
方法,經過測試用例
public String getResult() {
if (input % 15 == 0){
return "FizzBuzz";
}
if (input % 3 == 0){
return "Fizz";
}
if (input % 5 == 0){
return "Buzz";
}
return String.valueOf(input);
}
複製代碼
咱們編寫完測試用例,可是代碼出現了代碼的壞味道——重複代碼
,有了測試用例
,咱們就能夠很輕鬆
的重構代碼,接下來開始重構咱們的代碼。
public String getResult() {
if (isDivisibleBy(15)){
return "FizzBuzz";
}
if (isDivisibleBy(3)){
return "Fizz";
}
if (isDivisibleBy(5)){
return "Buzz";
}
return String.valueOf(input);
}
private boolean isDivisibleBy(int i) {
return input % i == 0;
}
複製代碼
抽取一個 isDivisibleBy
方法,而後運行測試,看看修改後是否引入bug
測試經過,沒問題,但在這裏咱們須要注意一點
每一次修改,都需運行一遍測試,避免修改引入
bug
,確保代碼的正確性
。
測試經過後,咱們繼續進一步優化。
public String getResult() {
String result = "";
if (isDivisibleBy(3)) {
result += "Fizz";
}
if (isDivisibleBy(5)) {
result += "Buzz";
}
return result;
}
複製代碼
繼續修改 getResult
方法,提取一個變量 result
做爲返回值,而後運行測試。
出乎意料,此次修改居然出現bug
,正如剛剛所說,每次修改後,都須要運行測試用例保證代碼的正確性。咱們再來檢查一下代碼,並做出以下修改:
public String getResult() {
String result = "";
if (isDivisibleBy(3)) {
result += "Fizz";
}
if (isDivisibleBy(5)) {
result += "Buzz";
}
if (result.isEmpty()){
result += input + "";
}
return result;
}
複製代碼
經過測試用例,發現當輸入爲1
的時候,沒有進行處理,添加相應判斷。再次
運行測試用例
測試經過,大功告成!
最後剩下遍歷 1~100
狀況,相信難不倒你,感興趣的朋友,能夠自行編寫~
至此,我儘可能演示一個相對完整的TDD開發
流程,麻雀雖小,五臟俱全。但願你能感覺到 get
到feel
~
咱們再來總結一下:
類
名推薦使用 駝峯式
命名,測試方法
推薦使用下劃線
命名需求
的範圍
和優先級
優先級
編寫寫測試用例
「紅燈」
時,咱們就應該動手編寫出,能經過測試的測試用例。「綠燈」
時,咱們就應該停下來思考,下一個測試用例改如何編寫。測試
,避免修改引入bug
,確保代碼的正確性
。完成功能
第5點,不分前後,能夠交替執行。
有些人以爲爲何要弄那麼複雜,還要浪費時間寫單元測試,爲什麼不
一把梭
呢?
沒有測試用例覆蓋的代碼,你敢保證代碼的質量嗎?
沒有測試用例覆蓋的代碼,你敢進行代碼重構嗎? 你品你細品 (滑稽)
其實TDD
開發模式,主要看開發者意願,不強求,可是單元測試
必須的!
以上就是所有內容,但願能幫助到你~ 若有不妥,歡迎指出,你們一塊兒交流學習。