qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          測(cè)試驅(qū)動(dòng)開發(fā)TDD(1)

           TDD
            今兒接到一需求如下:
            比如一個(gè)給定的數(shù)字2975,讓你去猜。6次機(jī)會(huì)。如果第一次輸入2509,系統(tǒng)會(huì)提示 1A2B:其中數(shù)字“2”位置猜對(duì)&&數(shù)字也猜對(duì)。稱為1A,而“9”和“5”數(shù)字猜對(duì)了但是位置沒有猜對(duì)。稱為2B。。如果輸入2975那么就是4個(gè)數(shù)字都猜對(duì)了并且位置也是對(duì)的系統(tǒng)提示4A0B。民間俗稱猜數(shù)字游戲:百度百科傳送門:http://baike.baidu.com/view/358630.htm。
            做個(gè)簡(jiǎn)單分析。客戶端輸入一個(gè)數(shù)字,經(jīng)過游戲內(nèi)部的猜測(cè),返回一個(gè)結(jié)果給客戶端。嗯,還好,不算難。由于準(zhǔn)備做TDD實(shí)踐。所以我們Test First.Why? 如果您對(duì)TDD不是很了解。就跟我一起做下去,顯然我也是新手。我們的目標(biāo)是“沒有蛀牙!”。
            準(zhǔn)備工作:VS任意一個(gè)版本(C#)、任意一款測(cè)試工具、紙、筆(真彩0.5的)。
            第一步:筆和紙拿出來。思考思考如何把這個(gè)小游戲拆分了。然后我們一步一步去完成它。寫一個(gè)To-Do-List。
            To-Do-List:
            猜測(cè)數(shù)字
            輸入驗(yàn)證
            生成答案
            輸入次數(shù)
            輸出猜測(cè)結(jié)果
            ...............
            暫時(shí)想起這么多。比如還有選擇游戲難度、輸入日志、重新開始游戲、中途退出等等。
            今天我要完成這個(gè)游戲的核心功能(猜測(cè)數(shù)字),我稱它為Guesser。傳入一個(gè)數(shù)字,返回一個(gè)結(jié)果。分析一下它可能輸出的幾種情況:4a0b(全對(duì))、 0a4b(數(shù)字全對(duì),位置全錯(cuò))、2a2b(一半一半)、0a0b(全錯(cuò))。這4個(gè)CASE應(yīng)該Cover了所有情況了。如果有補(bǔ)充,請(qǐng)F(tuán)ollow。
            今天的TO-DO-LIST:
            假設(shè)我們這局游戲的答案是2975。
            輸入“2975” 輸出4a0b。
            輸入“2957” 輸出2a2b。
            輸入“9257” 輸出0a4b。
            輸入“1348” 輸出0a0b。
            完成Guesser類.
            新建一個(gè)TEST 寫測(cè)試。
            開始第一個(gè)CASE:輸入2975 與答案正匹配,輸出4a0b 。
          [TestMethod]
          public void Test1()
          {
          var inputNumber = "2975";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("4a0b", actual);
          }
            這個(gè)測(cè)試方法的命名一眼好像看不出它要測(cè)什么。單獨(dú)看測(cè)試的名字很是迷茫。我們修改一下讓它看起來很整潔。一眼看上去就知道是啥意思。要測(cè)試什么。
          [TestMethod]
          public void should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right()
          {
          var inputNumber = "2975";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("4a0b", actual);
          }
            修改完之后在看這個(gè)方法的命名。 是不是清晰了很多。看到方法的命名應(yīng)該就能夠猜測(cè)到此方法是在什么情況下測(cè)試什么功能。
            OK。我們的第一個(gè)CASE搞定了。Run一下。
            編譯不通過!因?yàn)闆]有Guesser類。沒有Guess方法。
            為了讓CASE過。我們必須創(chuàng)建Guesser類以及Guess方法。
          public class Guesser
          {
          public string Guess(string inputNumber)
          {
          throw new System.NotImplementedException();
          }
          }
            現(xiàn)在編譯沒錯(cuò)誤了。在Run。
            有異常:System.NotImplementedException: The method or operation is not implemented.
            鬧心。為了不鬧心。Guess方法里簡(jiǎn)單實(shí)現(xiàn)。最簡(jiǎn)單的就是直接返回"4a0b"。這里還是簡(jiǎn)單的實(shí)現(xiàn)實(shí)現(xiàn)。
          public class Guesser
          {
          private const string AnswerNumber = "2975";
          public string Guess(string inputNumber)
          {
          var ACount = 0;
          var BCount = 0;
          for (var index = 0; index < AnswerNumber.Length; index++)
          {
          if (AnswerNumber[index]==inputNumber[index])
          {
          ACount++;
          }
          }
          return string.Format("{0}a{1}b", ACount, BCount);
          }
          }
            OK。但是我們內(nèi)部實(shí)現(xiàn)如此簡(jiǎn)單。不知道是否滿足第二個(gè)CASE呢。
            完成一個(gè)CASE要把它劃掉。
            To-Do-List:
            輸入“2975” 輸出4a0b。
            輸入“2957” 輸出2a2b。
            輸入“9257” 輸出0a4b。
            輸入“1348” 輸出0a0b。
            完成Guesser類.
            來第二個(gè)CASE:輸入9257與答案不匹配,但是所有數(shù)字都正確,輸出0a4b 。
            有了第一個(gè)CASE的經(jīng)驗(yàn),這里我們也同樣注意命名。
          [TestMethod]
          public void should_return_2a2b_when_input_numbers_all_figures_right_and_2_positions_right()
          {
          var inputNumber = "2957";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("2a2b", actual);
          }
          Run.....
            沒有PASS:Assert.AreEqual failed. Expected:<2a2b>. Actual:<2a0b>.
            我們接著去改guess方法,保證第二個(gè)CASE PASS。
          public class Guesser
          {
          private const string AnswerNumber = "2975";
          public string Guess(string inputNumber)
          {
          var aCount = 0;
          var bCount = 0;
          for (var index = 0; index < AnswerNumber.Length; index++)
          {
          if (AnswerNumber[index]==inputNumber[index])
          {
          aCount++;
          continue;
          }
          if (AnswerNumber.Contains(inputNumber[index].ToString()))
          {
          bCount++;
          }
          }
          return string.Format("{0}a{1}b", aCount, bCount);
          }
          }
            運(yùn)行所有CASE...pass.別忘記劃掉To-Do-List
           接下來把剩下的兩個(gè)CASE搞定。
          [TestMethod]
          public void should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right()
          {
          var inputNumber = "2975";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("4a0b", actual);
          }
          [TestMethod]
          public void should_return_2a2b_when_input_numbers_all_figures_right_and_2_positions_right()
          {
          var inputNumber = "2957";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("2a2b", actual);
          }
          [TestMethod]
          public void should_return_0a4b_when_input_numbers_all_figures_right_and_no_positions_right()
          {
          var inputNumber = "9257";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("0a4b", actual);
          }
          [TestMethod]
          public void should_return_0a0b_when_input_number_all_figures_and_positions_wrong()
          {
          var inputNumber = "1348";
          var actual = new Guesser().Guess(inputNumber);
          Assert.AreEqual("0a0b", actual);
          }
            運(yùn)行所有CASE...
            不知不覺我們已經(jīng)完成了今天的所有任務(wù)。
            To-Do-List:
            輸入“2975” 輸出4a0b。
            輸入“2957” 輸出2a2b。
            輸入“9257” 輸出0a4b。
            輸入“1348” 輸出0a0b。
            完成Guesser類.
            Go Home.然后別忘記把總的List劃掉。
            今天的任務(wù)完成。今天收獲是什么?
            (1)Test First。從用戶角度去思考問題。在設(shè)計(jì)CASE之前。會(huì)把關(guān)注點(diǎn)放到需求上。只有足夠透徹的了解需求。才能設(shè)計(jì)出正確全面的CASE。
            (2)命名。在最開始我們把Test1改成了‘should_return_4a0b_when_input_numbers_all_figures_and_positions_are_right’。看到方法名,就相當(dāng)于看到文檔。很快速的知道當(dāng)前方法測(cè)的是什么功能。而不需要去翻閱文檔。維護(hù)起來也是相當(dāng)清晰。不用花大把時(shí)間去維護(hù)文檔。
            當(dāng)然也有些疑問。
            (1)先寫測(cè)試在寫代碼開發(fā)速度降低了。
            帶著這些疑問。繼續(xù)做下去。希望在這個(gè)系統(tǒng)實(shí)現(xiàn)完之后能解決我的疑問。
            最后Yuheng同學(xué)提出了一個(gè)問題。
            有4個(gè)分別是[風(fēng)險(xiǎn)高 價(jià)值高]、[風(fēng)險(xiǎn)高 價(jià)值低]、[風(fēng)險(xiǎn)低 價(jià)值高]、[風(fēng)險(xiǎn)低 價(jià)值低]的事情,你會(huì)優(yōu)先做哪個(gè)?
            大家可以給出自己的答案。

          posted on 2014-01-16 11:38 順其自然EVO 閱讀(289) 評(píng)論(0)  編輯  收藏 所屬分類: selenium and watir webdrivers 自動(dòng)化測(cè)試學(xué)習(xí)

          <2014年1月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 五大连池市| 石门县| 汉川市| 福泉市| 全州县| 新巴尔虎左旗| 壶关县| 蕉岭县| 阿克苏市| 襄垣县| 六盘水市| 石林| 平定县| 开原市| 左云县| 大余县| 浮山县| 朝阳市| 临夏市| 德格县| 奉节县| 英德市| 长子县| 乐至县| 缙云县| 汉沽区| 习水县| 富裕县| 弥渡县| 武安市| 浦城县| 藁城市| 汝南县| 会泽县| 青海省| 林甸县| 惠安县| 虹口区| 辽宁省| 黄平县| 资中县|