Last active
August 29, 2015 14:18
-
-
Save mFingers/74b4b7c370a2c832ce6c to your computer and use it in GitHub Desktop.
Unit tests and production code for the credit card validator kata.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace CreditCardValidator { | |
public class CreditCard { | |
private string ccNumber; | |
private const int minThreshold = 13; | |
private const int maxThreshold = 16; | |
private readonly int[] substitutionDigits = new int[]{ | |
0, 2, 4, 6, 8, 1, 3, 5, 7, 9 | |
}; | |
public CreditCard(string creditCardNumber) { | |
ccNumber = creditCardNumber; | |
} | |
public bool IsValid() { | |
return | |
!String.IsNullOrEmpty(ccNumber) && | |
ccNumber.All(Char.IsDigit) && | |
ccNumber.Length <= maxThreshold && | |
ccNumber.Length >= minThreshold && | |
GetChecksum() % 10 == 0; | |
} | |
public int GetChecksum() { | |
return ConvertToNumbers(ccNumber) | |
.Select((c, i) => { | |
if (i % 2 == 0) { | |
return substitutionDigits[c]; | |
} | |
else { | |
return c; | |
} | |
}).Sum(); | |
} | |
private IEnumerable<int> ConvertToNumbers(string ccNumber) { | |
var asNumbers = ccNumber.PadLeft(maxThreshold, '0') | |
.Select(c => Int32.Parse(c.ToString())); | |
return asNumbers; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using NUnit.Framework; | |
namespace CreditCardValidator.Tests { | |
/* | |
* Test card numbers from http://testcreditcardnumbers.com/ | |
*/ | |
[TestFixture] | |
public class ValidateFixture { | |
[TestCase("")] | |
[TestCase(" ")] | |
[TestCase(null)] | |
public void EmptyCardNumber(string ccNumber) { | |
var cc = new CreditCard(ccNumber); | |
Assert.False(cc.IsValid()); | |
} | |
[TestCase("1234g6345")] | |
[TestCase("908234*&775")] | |
public void NonDigitCharactersAreInvalid(string ccNumber) { | |
var cc = new CreditCard(ccNumber); | |
Assert.False(cc.IsValid()); | |
} | |
[TestCase("111111111111", false)] | |
[TestCase("4222222222222", true)] | |
[TestCase("30569309025904", true)] | |
[TestCase("371449635398431", true)] | |
[TestCase("4111111111111111", true)] | |
[TestCase("11111111111111111", false)] | |
public void CreditCardLength(string ccNumber, bool isValid) { | |
var cc = new CreditCard(ccNumber); | |
Assert.AreEqual(isValid, cc.IsValid()); | |
} | |
[Test] | |
public void SixteenDigitChecksumSumsOddIndexes() { | |
var cc = new CreditCard("0101010101010101"); | |
Assert.AreEqual(8, cc.GetChecksum()); | |
} | |
[Test] | |
public void LessThanSixteenPadsToSixteenBeforeChecksumCalc() { | |
var cc = new CreditCard("0101010101010"); | |
Assert.AreEqual(12, cc.GetChecksum()); | |
} | |
[TestCase("0", 0)] | |
[TestCase("1", 2)] | |
[TestCase("2", 4)] | |
[TestCase("3", 6)] | |
[TestCase("4", 8)] | |
[TestCase("5", 1)] | |
[TestCase("6", 3)] | |
[TestCase("7", 5)] | |
[TestCase("8", 7)] | |
[TestCase("9", 9)] | |
public void SubstitutionLookups(string digit, int substitutionDigit) { | |
var cc = new CreditCard(digit + "000000000000000"); | |
Assert.AreEqual(substitutionDigit, cc.GetChecksum()); | |
} | |
[Test] | |
public void ChecksumNotEndingInZeroIsInvalid() { | |
var cc = new CreditCard("0101010101010101"); | |
Assert.False(cc.IsValid()); | |
} | |
[Test] | |
public void ValidCardNumberIsValid() { | |
var cc = new CreditCard("5111111111111118"); | |
Assert.True(cc.IsValid()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment