Advertisement
martinevans

Roy Osheroves Strings Kata

Nov 15th, 2012
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.60 KB | None | 0 0
  1. // My attempt at  http://osherove.com/tdd-kata-1/ using c# with nunit
  2. // @martin_evans - last updated 21 December 2012 [End of the world edition!]
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using NUnit.Framework;
  8.  
  9. namespace Kata
  10. {
  11.     [TestFixture]
  12.     public class StringCalculatorTests
  13.     {
  14.         private StringCalculator subject;
  15.  
  16.         [SetUp]
  17.         public void Setup()
  18.         {
  19.             subject = new StringCalculator();
  20.         }
  21.  
  22.         [Test]
  23.         public void Add_EmptyString_ReturnsZero()
  24.         {
  25.             Assert.AreEqual(0, subject.Add(string.Empty));
  26.         }
  27.  
  28.         [Test]
  29.         public void Add_OneNumber_ReturnNumericValue()
  30.         {
  31.             Assert.AreEqual(0, subject.Add("0"));
  32.         }
  33.  
  34.         [Test]
  35.         public void Add_TwoNumbers_ReturnSum()
  36.         {
  37.             Assert.AreEqual(3, subject.Add("1,2"));
  38.         }
  39.  
  40.         [Test]
  41.         public void Add_UnknownNumberCount_ReturnSum()
  42.         {
  43.             var rnd = new Random();
  44.             var numbers = "";
  45.             var count = rnd.Next(1, 1000);
  46.             var lst = new List<int>();
  47.  
  48.             for (var i = 0; i < count; i++)
  49.                 lst.Add(i);
  50.  
  51.             numbers = String.Join(",", lst.ToArray());
  52.  
  53.             Console.WriteLine("Testing with {0} numbers", count);
  54.  
  55.             Assert.AreEqual(lst.Sum(), subject.Add(numbers));
  56.  
  57.         }
  58.  
  59.         [Test]
  60.         public void Add_AllowNewLinesBetweenNumbersInsteadOfCommas_ReturnsSum()
  61.         {
  62.             Assert.AreEqual(6, subject.Add("1\n2,3"));
  63.         }
  64.  
  65.         [Test]
  66.         public void Add_SupportsChangingDelimiterAtBeginningOfString_ReturnsSum()
  67.         {
  68.             Assert.AreEqual(3, subject.Add("//;\n1;2"));
  69.         }
  70.  
  71.         [Test]
  72.         public void Add_NegativeNumber_ThrowsException()
  73.         {
  74.             Assert.Throws<Exception>(() => subject.Add("1,2,3,-4,-5"));
  75.         }
  76.  
  77.         [Test]
  78.         public void Add_NegativeNumber_ExceptionContainsNumbersInMessage()
  79.         {
  80.             const string exMsg = "negatives not allowed : -4,-5";
  81.  
  82.             try
  83.             {
  84.                 subject.Add("1,2,3,-4,-5");
  85.                 Assert.Fail();
  86.             }
  87.             catch (Exception ex)
  88.             {
  89.                 Assert.AreEqual(exMsg, ex.Message);              
  90.             }
  91.         }
  92.  
  93.         [Test]
  94.         public void Add_NumbersBiggerThan1000Included_ShouldBeIgnoredInCalcultion()
  95.         {
  96.             Assert.AreEqual(3, subject.Add("1,2,1001"));
  97.         }
  98.  
  99.         [Test]
  100.         public void Add_DelimitersOfAnyLength_Permitted()
  101.         {
  102.             Assert.AreEqual(6, subject.Add("//[***]\n1***2***3"));
  103.         }
  104.  
  105.         [Test]
  106.         public void Add_MultipleDelimiters_Permitted()
  107.         {
  108.             Assert.AreEqual(6, subject.Add("//[*][%]\n1*2%3"));
  109.         }
  110.  
  111.         [Test]
  112.         public void Add_MultipleDelimitersWithLengthLongerThanOneCharacter_Permitted()
  113.         {
  114.             Assert.AreEqual(6, subject.Add("//[fred][wilma]\n1fred2wilma3"));
  115.         }
  116.  
  117.     }
  118.  
  119.     public class StringCalculator
  120.     {
  121.         public int Add(string numbers)
  122.         {
  123.             if (string.IsNullOrEmpty(numbers))
  124.                 return 0;
  125.  
  126.             var numericVals = GetNumbersFromString(numbers);
  127.  
  128.             Validate(numericVals);
  129.  
  130.             return numericVals.Where(x=>x<=1000).Sum();
  131.         }
  132.  
  133.         private void Validate(IEnumerable<int> numericVals)
  134.         {
  135.             var negativenumbers = numericVals.Where(x => x < 0);
  136.  
  137.             if (negativenumbers.Any())
  138.             {
  139.                 var msg = string.Format("negatives not allowed : {0}", string.Join(",", negativenumbers));
  140.                 throw new Exception( msg);                
  141.             }    
  142.                
  143.                
  144.         }
  145.  
  146.         private static IEnumerable<int> GetNumbersFromString(string numbers)
  147.         {
  148.             var delimiters = new[]{","};
  149.  
  150.             if (numbers.StartsWith("//"))
  151.             {
  152.                 var n = numbers.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
  153.                 delimiters = n[0].Substring(2).Split(new[] {"[", "]"}, StringSplitOptions.RemoveEmptyEntries);                ;                                
  154.                 numbers = string.Join(delimiters[0], n.Skip(1));
  155.             }
  156.  
  157.             return  numbers
  158.                            .Replace("\n", delimiters[0])
  159.                            .Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
  160.                            .Select(Int32.Parse).ToArray();
  161.         }
  162.     }
  163. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement