[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 。

依据测试案例,建立的单元测试程序如下:


/// 
///GetsComapanyName 的测试
///
[TestMethod()]
public void GetsComapanyNameTest_v3()
{
    BlackCat target = new BlackCat();
    string expected = "黑猫";
    string actual;
    actual = target.GetsComapanyName();
    Assert.AreEqual(expected, actual);
}

/// 
///GetsFee 的测试
///
[TestMethod()]
public void GetsFeeTest_v3()
{
    BlackCat target = new BlackCat();
    double expected = 0F;
    double actual;
    actual = target.GetsFee();
    Assert.AreEqual(expected, actual);
}

/// 
///Calculate 的测试
///
[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 真的不难,但相关的每一份基本功,都要够扎实,才不会因为碰到一些门槛,就嫌弃测试无用,这实在非测试之罪啊…


或许您会对下列培训课程感兴趣:

  1. 2019/7/27(六)~2019/7/28(日):演化式设计:测试驱动开发与持续重构 第六梯次(中国台北)
  2. 2019/8/16(五)~2019/8/18(日):【C#进阶设计-从重构学会高易用性与高弹性API设计】第二梯次(中国台北)
  3. 2019/9/21(六)~2019/9/22(日):Clean Coder:DI 与 AOP 进阶实战 第二梯次(中国台北)
  4. 2019/10/19(六):【针对遗留代码加入单元测试的艺术】第七梯次(中国台北)
  5. 2019/10/20(日):【极速开发】第八梯次(中国台北)

想收到第一手公开培训课程资讯,或想询问企业内训、顾问、教练、咨询服务的,请洽 Facebook 粉丝专页:91敏捷开发之路。

原文:大专栏  [30天快速上手TDD][Day 14]Refactoring - 验货


猜你喜欢

转载自www.cnblogs.com/petewell/p/11516467.html