[30天快速上手TDD][Day 14]Refactoring - 驗貨

[30天快速上手TDD][Day 14]Refactoring - 驗貨

前言

在上一篇文章中,重構第五式:「給你錢,趕快做」中,重點在於如何站在當下物件的角度,去思考自身職責該處理的邏輯,並思考非自身職責的部分,該委託給哪一個物件來處理。

只管跟它要,而不管它怎麼做」,這就是第五式的精髓。

接下來這篇文章,則是怎麼驗證委託物件給的,真的是我們要的呢?

所以這一篇文章標題,定義為「驗貨」,重構第六式:「確定對方給的,是我要的

我們將先透過建立測試案例,來確保物件回傳的結果,是如同我們所預期。(這一篇文章的重構技巧,需要用到前面介紹的測試相關技巧)

 

重構第六式:確定對方給的,是我要的

在前面已經定義出來『我們要什麼,跟誰要』,接著是要確定『物流商給我們的資訊,是不是我們要的』。

怎麼確定物流商給的資訊沒錯?對啦,就是用測試啦。

正所謂羊毛出在羊身上,建立單元測試的測試案例,往往可以從一開始的整合測試案例中找到蛛絲馬跡,也就是我們一開始錄影存證的部份。

Selenium test cases 如下圖所示:

selenium test cases

期望結果(以黑貓為例):

  1. 呼叫黑貓的 GetsCompanyName 方法,應該得到『黑貓』。
  2. 還沒呼叫黑貓計算運費前,呼叫黑貓的 GetsFee 方法,應該得到 0 。
  3. 當給了整合測試上的商品資訊後,呼叫黑貓的 Calculate 方法後,呼叫 GetsFee 方法,應該得到 200 。

依據測試案例,建立的單元測試程式碼如下:


/// <summary>
///GetsComapanyName 的測試
///</summary>
[TestMethod()]
public void GetsComapanyNameTest_v3()
{
    BlackCat target = new BlackCat();
    string expected = "黑貓";
    string actual;
    actual = target.GetsComapanyName();
    Assert.AreEqual(expected, actual);
}

/// <summary>
///GetsFee 的測試
///</summary>
[TestMethod()]
public void GetsFeeTest_v3()
{
    BlackCat target = new BlackCat();
    double expected = 0F;
    double actual;
    actual = target.GetsFee();
    Assert.AreEqual(expected, actual);
}

/// <summary>
///Calculate 的測試
///</summary>
[TestMethod()]
public void CalculateTest_v3()
{
    //從整合測試的test case,來當做單元測試的test case

    //arrange
    BlackCat target = new BlackCat()
    {
        ShipProduct = new Product
        {
            IsNeedCool = true,
            Name = "商品測試1",
            Size = new Size
            {
                Height = 10,
                Length = 30,
                Width = 20
            },
            Weight = 10
        }
    };

    //act
    target.Calculate();

    
    var expectedName = "黑貓";
    var expectedFee = 200;

    var actualName = target.GetsComapanyName();
    var actualFee = target.GetsFee();

    //assert
    Assert.AreEqual(expectedName, actualName);
    Assert.AreEqual(expectedFee, actualFee);
}

註:對Unit test還不熟的朋友,可以參考本系列前面的鐵人賽文章:[30天快速上手TDD][Day 3]動手寫 Unit Test,或是[ASP.NET]重構之路系列v5 –單元測試, Just Do It!!

建立完我們預期物流商的行為,執行一下測試的結果,得到了 9 個紅燈,得到的例外都是『System.NotImplementedException: 方法或作業尚未實作』(因為我還沒發功啊)。如下圖所示:

單元測試結果

看到紅燈,莫急莫慌莫害怕,因為這是我們所設定這一次動作的終點線。(同時也是起點線,笑...)

慢慢地,各位讀者就會了解到,看到紅燈有種莫名的快感,只要把紅燈轉綠,就至少可以交差的感覺,更是妙不可言。

 

小結

雖然上面這一步碰到了 9 個紅燈,但是這個紅燈是一個很棒的里程碑,因為這是重構循環中,重要的一個紅燈。(基本上,也可以當作是 TDD 的紅燈)如下圖所示

循環圖

這一個紅燈,代表了我們已經邁出了第一步:「先思考好,使用者要什麼。」 接著,不管物件怎麼設計,程式寫的多爛、多沒彈性,我們都可以確定:「眼前這爛貨或是神蹟,到底能不能滿足我們的需求」。

TDD, Agile, Scrum ,都有個重要的精神:小步前進,迅速回饋,擁抱變化,隨時調整。

相同的目標,都是做出最吻合使用者需求的軟體。任何需求的異動,架構的調整,程式的改善,都是讓系統品質更加進化的方式,只有最符合使用者需求,系統才有所謂的價值。(順便推薦一本跟這相關的好書:浮現式設計-專業軟件開發的演進本質,原文書名:Emergent Design: The Evolutionary Nature of Professional Software Development

做再好的軟體,全世界沒人用,那就真的是一坨金子堆出來的廢物。亮晶晶,也很貴,但仍是廢物。

by the way, 眼尖的讀者朋友應該已經發現,重構系列中會開始不斷運用到本系列前面的第一大主題:測試的目的、技巧、工具與方式。這也是為什麼第一篇總綱,就先定義出 TDD 各大主題的學習順序,與實際開發時的順序不太相同。

TDD 真的不難,但相關的每一份基本功,都要夠紮實,才不會因為碰到一些門檻,就嫌棄測試無用,這實在非測試之罪啊…

對敏捷開發有興趣的朋友,可以參考我的粉絲專頁:91敏捷開發之路

對 TDD 課程有興趣的朋友,課程內容、大綱與學員心得,可以參考 skilltree 的公開課程:自動測試與 TDD 實務開發

若需要聯絡我,可以透過粉絲專頁私訊或是側欄的關於我。