TDD by example (6) -- 无招

继续我们的TDD,还是先看to-do list

  随机生成答案
  检查输入是否合法 
   判断猜测结果
  记录历史猜测数据并显示 
  判断猜测次数,如果满6次但是未猜对则判负  
  如果4个数字全中,则判胜
  
  实现IRandomIntGenerator 
  实现IGameHistory
  显示猜测纪录

检查输入是否合法

还是测试先行
[Test]
public   void  should_return_true_when_input_is_valid()
{
    InputValidator validator 
=   new  InputValidator();
    Assert.That(validator.Validate(
" 1 2 3 4 " ), Is.True);
}
还是先写功能代码让编译通过,然后运行测试,红了,接着把功能代码写完让测试变绿
public   class  InputValidator
{
    
public   bool  Validate( string  input)
    {
        
return   true ;
    }
}
这里我只是简单的返回了true,第一,我现在的任务就是让测试通过,而返回true就已经满足条件了;第二因为我们还没写输入错误的测试,因此不需要先考虑错误的情况。
接下来写几个测试输入错误的测试,先写一个测试输入元素数量多于4个的测试,顺便把validator的构造提取到setup里
private  InputValidator validator;
[SetUp]
public   void  Setup()
{
    validator 
=   new  InputValidator();
}
[Test]
public   void  should_return_false_when_input_has_more_numbers_than_four()
{
    Assert.That(validator.Validate(
" 1 2 3 4 5 " ), Is.False);
}

public   bool  Validate( string  input)
{
    
string [] numbers  =  input.Split( new  []{ '   ' }, StringSplitOptions.RemoveEmptyEntries);
    
if  (numbers.Length  >   4 )
    {
        
return   false ;
    }
    
return   true ;
}
再写一个输入元素少于4个的
[Test]
public   void  should_return_false_when_input_has_less_numbers_than_four()
{
    Assert.That(validator.Validate(
" 1 2 3 " ), Is.False); 
}
public   bool  Validate( string  input)
{
    
string [] numbers  =  input.Split( new  []{ '   ' }, StringSplitOptions.RemoveEmptyEntries);
    
if  (numbers.Length  !=   4 )
    {
        
return   false ;
    }
    
return   true ;
}
下面测试输入的元素是不是都是整数
[Test]
public   void  should_return_false_when_input_contains_non_number()
{
    Assert.That(validator.Validate(
" 1 d 3 4 " ), Is.False);
}

public   bool  Validate( string  input)
{
    
string [] numbers  =  input.Split( new [] {  '   '  }, StringSplitOptions.RemoveEmptyEntries);
    
if  (numbers.Length  !=   4 )
    {
        
return   false ;
    }
    
foreach  (var num  in  numbers)
    {
        
int  result;
        
if  ( ! int .TryParse(num,  out  result))
        {
            
return   false ;
        }
    }
    
return   true ;
}
测试输入的数是否在0-9之间
[Test]
public   void  should_return_false_when_input_nunbers_is_not_between_zero_and_nine()
{
      Assert.That(validator.Validate(
" 1 2 10 -1 " ), Is.False);
}
public   bool  Validate( string  input)
{
    
string [] numbers  =  input.Split( new [] {  '   '  }, StringSplitOptions.RemoveEmptyEntries);
    
if  (numbers.Length  !=   4 )
    {
        
return   false ;
    }
    
foreach  (var num  in  numbers)
    {
        
int  result;
        
if  ( ! int .TryParse(num,  out  result))
        {
            
return   false ;
        }
        
if  (result  <   0   ||  result  >   9 )
        {
            
return   false ;
        }
    }
    
return   true ;
}
测试输入的数是否有重复的
[Test]
public   void  should_return_false_when_input_contains_repeat_nunbers()
{
    Assert.That(validator.Validate(
" 1 1 2 3 " ), Is.False);
}

写代码通过测试并重构
ExpandedBlockStart.gif Code
public class InputValidator
{
    
private const int InputLength = 4;
    
private const int MaxNum = 9;
    
private const int MinNum = 0;

    
public bool Validate(string input)
    {
        
string[] numbers = input.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
        
return IsInputLengthCorrect(numbers)
               
&& IsInputAreAllInteger(numbers)
               
&& IsInputAreAllBetweenZeroAndNine(numbers)
               
&& IsUnique(numbers);
    }

    
private static bool IsInputAreAllBetweenZeroAndNine(IEnumerable<string> numbers)
    {
        
return numbers.All(numStr => Convert.ToInt32((string) numStr).IsBetween(MinNum, MaxNum));
    }

    
private static bool IsInputLengthCorrect(ICollection<string> numbers)
    {
        
bool correct = numbers.Count == InputLength;
        
return correct;
    }

    
private static bool IsInputAreAllInteger(IEnumerable<string> numbers)
    {
        
int num;
        
return numbers.All(number => int.TryParse(number, out num));
    }

    
private static bool IsUnique(IEnumerable<string> numbers)
    {
        
return numbers.Distinct().Count() == InputLength;
    }
}


实现IGameHistory

ExpandedBlockStart.gif Test
[TestFixture]
public class TestGameHistory
{
    [Test]
    
public void should_get_histories_in_order()
    {
        var history 
= new GameHistory();
        history.Add(
new[] {1234}, "0A0B");
        history.Add(
new[] {2345}, "0A2B");
        history.Add(
new[] {4567}, "1A2B");

        var expectedResult 
= new StringBuilder();
        expectedResult.AppendLine(
"1 2 3 4 : 0A0B");
        expectedResult.AppendLine(
"2 3 4 5 : 0A2B");
        expectedResult.AppendLine(
"4 5 6 7 : 1A2B");

        Assert.That(history.GetAll(), Is.EqualTo(expectedResult.ToString()));
    }
}

 

ExpandedBlockStart.gif Code
public class GameHistory : IGameHistory
{
    
private readonly List<string> histories = new List<string>();

    
#region IGameHistory Members

    
public void Add(int[] guess, string guessResult)
    {
        var oneHistory 
= new StringBuilder();
        
foreach (int num in guess)
        {
            oneHistory.AppendFormat(
"{0} ", num);
        }
        oneHistory.AppendFormat(
": {0}", guessResult);
        histories.Add(oneHistory.ToString());
    }

    
public string GetAll()
    {
        var output 
= new StringBuilder();
        
foreach (string history in histories)
        {
            output.AppendLine(history);
        }
        
return output.ToString();
    }

    
#endregion
}


实现IRandomIntGenerator 

ExpandedBlockStart.gif Code
public class RandomIntGenerator : IRandomIntGenerator
{
    
private readonly Random random;

    
public RandomIntGenerator()
    {
        random 
= new Random();
    }

    
#region IRandomIntGenerator Members

    
public int Next()
    {
        
return random.Next(010);
    }

    
#endregion
}

 这里并没有再写测试了,一个原因是这个类比较简单,另一个原因是它的主要逻辑都委托给了标准库,而且Random很难测试。

Todo-list
  随机生成答案
  检查输入是否合法 
   判断猜测结果
  记录历史猜测数据并显示 
  判断猜测次数,如果满6次但是未猜对则判负  
  如果4个数字全中,则判胜
  
   实现IRandomIntGenerator  
  实现IGameHistory
  将所有连接起来( 显示猜测纪录

我们已经完成了大部分工作,各个功能模块(类)都已经搭建出来,最后一步就是将他们连接起来形成完整的程序。

转载于:https://www.cnblogs.com/wangyh/archive/2009/09/22/TDD-By-Example-6.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值