using System.Collections.Generic;
using System.Text.RegularExpressions;
private static IEnumerable<TestCase> TestCases => new [] {
TestCase.For("12-1234-1234567").ExpectBankToBe("12"),
TestCase.For("12-1234-1234567").ExpectBranchToBe("1234"),
TestCase.For("12-1234-1234567").ExpectStemToBe("1234567"),
TestCase.For("12-1234-1234567").ExpectNormalizedFormattedNotationToBe("12-1234-1234567"),
TestCase.For("I-AM-NOT-A-VALID-ACCOUNT").ExpectToFail(),
TestCase.For("121234123456701").ExpectToFail(),
public static void Main()
foreach(var testCase in TestCases) {
BankAccountNumberTest(testCase);
static void BankAccountNumberTest(TestCase testCase) {
Console.WriteLine($"Test: {testCase}");
if(testCase.ExpectFailure)
BankAccountNumberNegativeTest(testCase.Input);
BankAccountNumberHappyTest(testCase);
static void BankAccountNumberHappyTest(TestCase testCase)
var actual = BankAccountNumber.ParseBankAccountNumber(testCase.Input);
if(testCase.ExpectedBank != null)
actual.Bank.Should().Be(testCase.ExpectedBank);
if(testCase.ExpectedBranch != null)
actual.Branch.Should().Be(testCase.ExpectedBranch);
if(testCase.ExpectedStem != null)
actual.Stem.Should().Be(testCase.ExpectedStem);
if(testCase.ExpectedFormatted != null)
actual.ToString().Should().Be(testCase.ExpectedFormatted);
Console.WriteLine("PASS.\n");
Console.WriteLine("FAIL: " + e.Message);
static void BankAccountNumberNegativeTest(string input)
Console.WriteLine($"Negative Test: {input}");
BankAccountNumber.ParseBankAccountNumber(input);
Console.WriteLine("FAIL: expectedFormatException");
catch(FormatException e) {
var expectedMessage = $"FacilityNumb is not in format 00 - 0000 - 0000000 - 00 - 000. Got '{input}'";
if(e.Message != expectedMessage)
Console.WriteLine($"FAIL: expected FormatException to have message \"{expectedMessage}\", but got \"{e.Message}\"");
Console.WriteLine("PASS.\n");
Console.WriteLine("FAIL: expected FormatException, but got " + e);
Console.WriteLine($"{pass} / {pass + fail} tests passed.\n");
Console.WriteLine(fail == 0 ? "SUCCESS!" : "FAILURE!");
public static TestCase For(string input) => new TestCase(input);
public TestCase(string input) { Input = input; }
public string Input { get; }
public string? ExpectedBank;
public string? ExpectedBranch;
public string? ExpectedStem;
public string? ExpectedFormatted;
public bool ExpectFailure;
public TestCase ExpectBankToBe(string bank) {
public TestCase ExpectBranchToBe(string branch) {
public TestCase ExpectStemToBe(string stem) {
public TestCase ExpectNormalizedFormattedNotationToBe(string formatted) {
ExpectedFormatted = formatted;
public TestCase ExpectToFail() {
public override string ToString() {
return $"{Input}, Expecting failure";
return $"{Input} - Expecting: "
+ $"{(ExpectedBank != null ? $"Bank={ExpectedBank}, " : "")}"
+ $"{(ExpectedBranch != null ? $"Branch={ExpectedBranch}, " : "")}"
+ $"{(ExpectedStem != null ? $"Stem={ExpectedStem}, " : "")}"
+ $"{(ExpectedFormatted != null ? $"Formatted={ExpectedFormatted}, " : "")}";
public class BankAccountNumber
protected BankAccountNumber() {}
public string Bank => "12";
public string Branch => "1234";
public string Stem => "1234567";
static Regex ValidPattern = new Regex(@"^\d{2}-\d{4}-\d{7}$", RegexOptions.Compiled);
public static BankAccountNumber ParseBankAccountNumber(string formattedBankAccountNumber)
if (formattedBankAccountNumber.Length > 15) {
throw FormatException(formattedBankAccountNumber);
if (!ValidPattern.IsMatch(formattedBankAccountNumber)) {
throw FormatException(formattedBankAccountNumber);
return new BankAccountNumber();
public override string ToString() {
return "12-1234-1234567";
static FormatException FormatException(string formattedBankAccountNumber)
return new FormatException($"FacilityNumb is not in format 00 - 0000 - 0000000 - 00 - 000. Got '{formattedBankAccountNumber}'");
public class FacilityNumber : BankAccountNumber
private FacilityNumber() : base() {}
public string Suffix => throw new NotImplementedException();
public string PaymentNumber => throw new NotImplementedException();
public static FacilityNumber ParseFacilityNumber(string formattedFacilityNumber)
throw new NotImplementedException();