zoukankan      html  css  js  c++  java
  • TDD实验1

    用户故事:我们要找一个女朋友,这个女朋友要能够管理财务。

    1. 先创建一个工程,引入NUnit,我们这里用这个做单元测试。

    image

    2. 设定,调试时启动Nunit

    image

    3. 写一个测试类

    首先我们需要一个有一个能管财务女朋友。

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using NUnit.Framework;

    namespace FindGrilFriendTest

    {

        [TestFixture]

        public class TestGrilFriend

        {

            [Test]

            public void IsFinanceAbility()

            {

                GrilFriend myGril = new GrilFriend();

                Assert.IsNotNull(myGril);

            }

        }

    }

    4.现在启动Debug

    image

     5. 我们发现这个都无法编译通过,因为没有GrilFriend类

    image

    6. 我们利用重构工具,生成GrilFriend类

    image

     namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public GrilFriend()

            {

                throw new NotImplementedException();

            }

        }

        [TestFixture]

        public class TestGrilFriend

        {

            [Test]

            public void IsFinanceAbility()

            {

                GrilFriend myGril = new GrilFriend();

                Assert.IsNotNull(myGril);

            }

        }

    }

    我们把这个类提到一个单独的文件叫GrilFriend.cs, 运行测试

    image

    7. 为了让测试通过,我们去掉构造函数里的那句

    using System;

    namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public GrilFriend()

            {

            }

        }

    }

    测试通过,看到绿色,好爽

    image

     

    8. 先在我们测试grilFriend是否有财务能力。

    using System;

    using NUnit.Framework;

    namespace FindGrilFriendTest

    {

     

       [TestFixture]

        public class TestGrilFriend

        {

            [Test]

            public void IsFinanceAbility()

            {

                GrilFriend myGril = new GrilFriend();

                Assert.IsNotNull(myGril);

                bool strongGrilFriend=myGril.IsFinanceAbility();

                if (strongGrilFriend)

                {

                    Console.Out.WriteLine("Yes,she is suit for my grilfriend");

                }

            }

        }

    }

    编译失败,因为我们的GrilFriend类里没有IsFinanceAbility方法。同样重构
    image
     

    using System;

    namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public GrilFriend()

            {

            }

            internal bool IsFinanceAbility()

            {

                throw new NotImplementedException();

            }

        }

    }

    编译明显失败。修改为

        internal bool IsFinanceAbility()

            {

                return true;

            }

        }

    测试Pass,绿色,爽。

    9. 现在我们的这个girlFriend不喜欢财务,所以我们现在加一个功能,就是这个girlFriend找个女佣来算帐。

    internal bool IsFinanceAbility()
           {

                Servant myServant = new Servant();

                if (myServant.CouldCalc())

                {

                    return true;

                }

                else

                {

                    return false;

                }

            }

    10. 编译没法通过,因为这个Servant还没有创建,我们可以立即创建一个Servant类,加上CouldCalc方法,但问题是,这些都让我们自己加的话,我们要累死了,所以我们想让Servant这个类让另一个开发人员Bill来写,Bill说:“好,但是我用一天的时间”,哎,难道我们需要等一天?这时候我们想到了接口,于是我们修改代码

    using System;

    namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public IServant myServant;

            public GrilFriend()

            {

            }

            internal bool IsFinanceAbility()

            {

                if (myServant.CouldCalc())

                {

                    return true;

                }

                else

                {

                    return false;

                }

            }

        }

    }
     

    using System;

    using System.Collections.Generic;

    using System.Text;

    namespace FindGrilFriendTest

    {

        public interface IServant

        {

            bool CouldCalc();

        }

    }

    这时候,我们的girlFriend需要测试这个仆人会不会计算,但我们如何如何判断,上面的方法无法判断,仆人不做任何工作,只要Return true,就骗过girlFriend了。现在我们改写这个测试方法为,如果我传一个数,他能把这个数乘以2,我们就认为他可以.

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace FindGrilFriendTest

    {

        public interface IServant

        {

            long CouldCalc(int i);

        }

    }

    这个时候接口定义完了,Bill说:“我将来开发的这个类就提供这个功能,我现在腐败去了”。
     
    这个时候,我们又想到,是呀,GirlFriend也不能这么测她的财务能力,我们重构测试代码如下

    using System;

    using NUnit.Framework;

    namespace FindGrilFriendTest

    {

       [TestFixture]

        public class TestGrilFriend

        {

            [Test]

            public void IsFinanceAbility()

            {

                GrilFriend myGril = new GrilFriend();

                Assert.IsNotNull(myGril);

                Random r = new Random(1000);

                int i = r.Next();

                long strongGrilFriend=myGril.IsFinanceAbility(i);

                if (strongGrilFriend==2*i)

                {

                    Console.Out.WriteLine("Yes,she is suit for my grilfriend");

                }

            }

        }

    }

    Test失败,修改grilFriend类

    using System;
     

    namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public IServant myServant;

            public GrilFriend()

            {

     

            }

            internal long IsFinanceAbility(int i)

            {

                return myServant.CouldCalc(i);

            }

        }

    }

    测试,还是失败

    image

    看错误信息,是有对象没有实例化,我们Debug一下,发现 return myServant.CouldCalc(i)出错; myServant没有实例化,是因为Bill还没有开发具体类,但是现在把Bill叫回来,还是继续等待,看来都不是好方法,这个时候,我们有的人可能觉得我自己先写一个类来模拟一下,可是如果这样,当Bill完成后,我们还的需要改代码,这个时候,一个东西迅速出现在脑海里,那就是Mock

    现在我们修改测试类

    using System;

    using NUnit.Framework;

    using Rhino.Mocks;

    namespace FindGrilFriendTest

    {

       [TestFixture]

        public class TestGrilFriend

        {

            [Test]

            public void IsFinanceAbility()

            {

                GrilFriend myGril = new GrilFriend();

                Assert.IsNotNull(myGril);

                Random r = new Random(1000);

                int i = r.Next();

                MockRepository mockRepository = new MockRepository();

                IServant mockServant = mockRepository.CreateMock<IServant>();

                Expect.Call(mockServant.CouldCalc(i)).Return(2 * i);

                mockRepository.ReplayAll();

                myGril.myServant = mockServant;

                long strongGrilFriend=myGril.IsFinanceAbility(i);

                mockRepository.VerifyAll();

                if (strongGrilFriend==2*i)

                {

                    Console.Out.WriteLine("Yes,she is suit for my grilfriend");

                }

     

            }

        }

    }

    修改grilFriend类,这里把internal改为public

    using System;

     

    namespace FindGrilFriendTest

    {

        public class GrilFriend

        {

            public IServant myServant;

            public GrilFriend()

            {

     

            }

            public long IsFinanceAbility(int i)

            {

                if (myServant != null)

                {

                    return myServant.CouldCalc(i);

                }

                else

                {

                    return 0;

                }

            }

        }

    }

     

    测试,哇,通过了。绿色,好爽.

    image

    至此,我们完成了我们的功能,找到一个适合自己的女朋友。Bill这个时候还在腐败呢。

     

    总结:

    这是我自己用TDD的方式第一次体验,当然我对TDD还不怎么了解,现在感觉是看到绿色很爽,写完代码有了测试代码了,而且过程中多次修正自己的设计。不好的地方是时间大大超过预期。如果哪位仁兄能够提供一些更好的TDD guideline,再次非常感谢。

     

    问题:这里我们看到,找servant应该是girlFriend类自己的事,现在却需要我们传进去,可是内部如果实例化,我们又没法Mock,因为Mock只能写在测试代码里。这让我想到了IOC, 但是还没实验,下节我试试IOC能否解决。

     

    本文写于:2008-12-03 23:50 王德水

     

  • 相关阅读:
    Redis安装与基本配置(转)
    redis和redis php扩展安装(转)
    fscanf()函数具体解释
    Android Studio非gradleproject编译后的apk文件在哪?
    Android利用CountDownTimer类实现倒计时功能
    Linux系统的安装
    由一个LED闪烁问题发现的MTK的LED driver中存在的问题
    OA系统权限管理设计(转载)
    Android开发之Mediaplayer
    “两地分居”的大学师生
  • 原文地址:https://www.cnblogs.com/cnblogsfans/p/1347441.html
Copyright © 2011-2022 走看看