From d4385a049340091182e7dcc571e15e0bc52e4a4f Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Thu, 13 Oct 2016 08:10:53 -0400 Subject: [PATCH 1/6] harry-potter exercise Based on cyber-dojo kata --- exercises/harry-potter/HarryPotterTests.dpr | 60 ++++++ exercises/harry-potter/HarryPotterTests.dproj | 176 ++++++++++++++++++ .../harry-potter/uHarryPotterExample.pas | 162 ++++++++++++++++ exercises/harry-potter/uHarryPotterTests.pas | 144 ++++++++++++++ 4 files changed, 542 insertions(+) create mode 100644 exercises/harry-potter/HarryPotterTests.dpr create mode 100644 exercises/harry-potter/HarryPotterTests.dproj create mode 100644 exercises/harry-potter/uHarryPotterExample.pas create mode 100644 exercises/harry-potter/uHarryPotterTests.pas diff --git a/exercises/harry-potter/HarryPotterTests.dpr b/exercises/harry-potter/HarryPotterTests.dpr new file mode 100644 index 00000000..400e4303 --- /dev/null +++ b/exercises/harry-potter/HarryPotterTests.dpr @@ -0,0 +1,60 @@ +program HarryPotterTests; + +{$IFNDEF TESTINSIGHT} +{$APPTYPE CONSOLE} +{$ENDIF}{$STRONGLINKTYPES ON} +uses + System.SysUtils, + {$IFDEF TESTINSIGHT} + TestInsight.DUnitX, + {$ENDIF } + DUnitX.Loggers.Console, + DUnitX.Loggers.Xml.NUnit, + DUnitX.TestFramework, + uHarryPotterTests in 'uHarryPotterTests.pas', + uHarryPotter in 'uHarryPotter.pas'; + +var + runner : ITestRunner; + results : IRunResults; + logger : ITestLogger; + nunitLogger : ITestLogger; +begin +{$IFDEF TESTINSIGHT} + TestInsight.DUnitX.RunRegisteredTests; + exit; +{$ENDIF} + try + //Check command line options, will exit if invalid + TDUnitX.CheckCommandLine; + //Create the test runner + runner := TDUnitX.CreateRunner; + //Tell the runner to use RTTI to find Fixtures + runner.UseRTTI := True; + //tell the runner how we will log things + //Log to the console window + logger := TDUnitXConsoleLogger.Create(true); + runner.AddLogger(logger); + //Generate an NUnit compatible XML File + nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); + runner.AddLogger(nunitLogger); + runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests; + + //Run tests + results := runner.Execute; + if not results.AllPassed then + System.ExitCode := EXIT_ERRORS; + + {$IFNDEF CI} + //We don't want this happening when running under CI. + if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then + begin + System.Write('Done.. press key to quit.'); + System.Readln; + end; + {$ENDIF} + except + on E: Exception do + System.Writeln(E.ClassName, ': ', E.Message); + end; +end. diff --git a/exercises/harry-potter/HarryPotterTests.dproj b/exercises/harry-potter/HarryPotterTests.dproj new file mode 100644 index 00000000..babb77fe --- /dev/null +++ b/exercises/harry-potter/HarryPotterTests.dproj @@ -0,0 +1,176 @@ + + + {00833D4E-9C22-4AE8-8578-81B63523F423} + 15.3 + None + HarryPotterTests.dpr + True + Debug + Win32 + 1 + Console + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + $(BDS)\bin\delphi_PROJECTICNS.icns + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + $(DUnitX);$(DCC_UnitSearchPath) + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + + + FireDACASADriver;FireDACSqliteDriver;bindcompfmx;DBXSqliteDriver;FireDACPgDriver;FireDACODBCDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;FireDACCommon;bindcomp;DBXInterBaseDriver;DataSnapCommon;xmlrtl;ibxpress;DbxCommonDriver;IndyProtocols;dbxcds;DBXMySQLDriver;FireDACCommonDriver;soaprtl;bindengine;bindcompdbx;FMXTee;fmxFireDAC;FireDACADSDriver;CustomIPTransport;FireDAC;dsnap;IndyIPServer;fmxase;IndyCore;IndyIPCommon;CloudService;FireDACIBDriver;FmxTeeUI;inet;fmxobj;FireDACMySQLDriver;inetdbxpress;fmxdae;RESTComponents;FireDACMSAccDriver;dbexpress;IndyIPClient;$(DCC_UsePackage) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + 1033 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + frxDB19;L208_r140;FireDACASADriver;FireDACSqliteDriver;bindcompfmx;DBXSqliteDriver;AbbreviaVCL;vcldbx;FireDACPgDriver;FireDACODBCDriver;S404_r;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;FireDACCommon;bindcomp;TeeDB;frx19;vclib;inetdbbde;DBXInterBaseDriver;Tee;DataSnapCommon;vclFireDAC;Rave110VCL;xmlrtl;svnui;ibxpress;DbxCommonDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;FireDACCommonDriver;MetropolisUILiveTile;O408_r;soaprtl;bindengine;vclactnband;vcldb;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;AsyncPro;vclie;XMLPartner_PR;fmxFireDAC;FireDACADSDriver;vcltouch;CustomIPTransport;G114_R140;vclribbon;VclSmp;FireDAC;dsnap;IndyIPServer;Intraweb;fmxase;vcl;IndyCore;VCLRESTComponents;IndyIPCommon;CloudService;CodeSiteExpressPkg;dsnapcon;FireDACIBDriver;FmxTeeUI;inet;fmxobj;E111_R120;FireDACMySQLDriver;vclx;inetdbxpress;svn;fmxdae;frxe19;RESTComponents;bdertl;FireDACMSAccDriver;adortl;dbexpress;IndyIPClient;$(DCC_UsePackage) + + + FireDACASADriver;FireDACSqliteDriver;bindcompfmx;DBXSqliteDriver;AbbreviaVCL;FireDACPgDriver;FireDACODBCDriver;fmx;rtl;dbrtl;DbxClientDriver;IndySystem;FireDACCommon;bindcomp;TeeDB;vclib;DBXInterBaseDriver;Tee;DataSnapCommon;vclFireDAC;xmlrtl;ibxpress;DbxCommonDriver;vclimg;IndyProtocols;dbxcds;DBXMySQLDriver;FireDACCommonDriver;MetropolisUILiveTile;O408_r;soaprtl;bindengine;vclactnband;vcldb;bindcompdbx;vcldsnap;bindcompvcl;FMXTee;TeeUI;vclie;fmxFireDAC;FireDACADSDriver;vcltouch;CustomIPTransport;vclribbon;VclSmp;FireDAC;dsnap;IndyIPServer;Intraweb;fmxase;vcl;IndyCore;VCLRESTComponents;IndyIPCommon;CloudService;dsnapcon;FireDACIBDriver;FmxTeeUI;inet;fmxobj;FireDACMySQLDriver;vclx;inetdbxpress;fmxdae;RESTComponents;FireDACMSAccDriver;adortl;dbexpress;IndyIPClient;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + HarryPotterTests.dpr + + + + + False + True + False + + + 12 + + + + diff --git a/exercises/harry-potter/uHarryPotterExample.pas b/exercises/harry-potter/uHarryPotterExample.pas new file mode 100644 index 00000000..d1eb0969 --- /dev/null +++ b/exercises/harry-potter/uHarryPotterExample.pas @@ -0,0 +1,162 @@ +unit uHarryPotter; + +interface + +type + Ihp = interface(IInvokable) + ['{22B4BAF3-88E6-456D-9DE5-F6BAC743A655}'] + function BasketTotal:extended; + function NumberOfDifferentBooks(inStr : string):integer; + function GroupBasket:TArray; + function GetSingleBookPrice: extended; + function GetBasket: string; + procedure SetBasket(aValue: string); + property Basket: string read GetBasket write SetBasket; + property SingleBookPrice: extended read GetSingleBookPrice; + end; + +function NewHPBasket: Ihp; + +implementation +uses System.SysUtils; + +const + hpBooks = '123456'; + cNumberOfBooks = 5; + cDiscounts: array[1..cNumberOfBooks] of extended = (1.00, + 0.95, + 0.90, + 0.80, + 0.75); + +type + Thp = class(TInterfacedObject, Ihp) + private + fSingleBookPrice: extended; + fBasket: string; + Group: TArray; + class function Head(inStr: string): string; static; + class function Tail(inStr: string): string; static; + function GetSingleBookPrice: extended; + function DiscountPercentage(inStr : string): extended; + procedure SetBasket(aValue: string); + function GetBasket: string; + public + function BasketTotal:extended; + function NumberOfDifferentBooks(inStr : string):integer; + function GroupBasket:TArray; + property SingleBookPrice: extended read GetSingleBookPrice; + property Basket: string read GetBasket write SetBasket; + constructor Create; + end; + +function NewHPBasket: Ihp; +begin + result := Thp.Create; +end; + +class function Thp.Head(inStr : string):string; +begin + result := inStr.Remove(1); +end; + +class function Thp.Tail(inStr : string):string; +begin + result := inStr.Remove(0,1); +end; + +constructor Thp.Create; +begin + fSingleBookPrice := 8; + fBasket := ''; +end; + +function Thp.GetSingleBookPrice; +begin + result := fSingleBookPrice; +end; + +procedure Thp.SetBasket(aValue: string); +begin + fBasket := aValue; +end; + +function Thp.GetBasket: string; +begin + result := fBasket; +end; + +function Thp.GroupBasket:TArray; +var lStrArray: TArray; + wrkBasket: string; + tmpStr : string; + thisBook : string; + Index : integer; + StrCount : integer; +begin + wrkBasket := fBasket; + StrCount := 1; + SetLength(lStrArray,StrCount); + thisBook := Head(wrkBasket); + while wrkBasket.Length > 0 do + begin + Index := 0; + repeat + tmpStr := lStrArray[Index]; + if thisBook.Length > 0 then + begin + if not tmpStr.Contains(thisBook) then + begin + tmpStr := tmpStr + thisBook; + lStrArray[Index] := tmpStr; + wrkBasket := Tail(wrkBasket); + thisBook := Head(wrkBasket); + end + else + if (Index = StrCount - 1) then + begin + inc(StrCount); + SetLength(lStrArray,StrCount); + end; + inc(Index); + end; + until (Index = StrCount) or wrkBasket.IsEmpty; + end; + result := lStrArray; +end; + +function Thp.BasketTotal:extended; +var hpBook : char; + totalBooks : integer; + subBaskets : TArray; + wrkSubBasket: string; + subTotal : extended; +begin + subBaskets := GroupBasket; + result := 0; + for wrkSubBasket in subBaskets do + begin + totalBooks := wrkSubBasket.Length; + subTotal := totalBooks * (fSingleBookPrice * DiscountPercentage(wrkSubBasket)); + result := result + subTotal; + end; +end; + +function Thp.DiscountPercentage(inStr : string):extended; +var numDiffBooks: integer; +begin + result := 1; + numDiffBooks := NumberOfDifferentBooks(inStr); + result := CDiscounts[numDiffBooks]; +end; + +function Thp.NumberOfDifferentBooks(inStr : string):integer; +var hpBook: char; +begin + result := 0; + for hpBook in hpBooks do + if inStr.Contains(hpBook) then + inc(result); +end; + +end. diff --git a/exercises/harry-potter/uHarryPotterTests.pas b/exercises/harry-potter/uHarryPotterTests.pas new file mode 100644 index 00000000..551eedbd --- /dev/null +++ b/exercises/harry-potter/uHarryPotterTests.pas @@ -0,0 +1,144 @@ +unit uHarryPotterTests; + +interface +uses + DUnitX.TestFramework, uHarryPotter; + +type + + [TestFixture] + hpTests = class(TObject) + private + fHP: Ihp; + public + [Setup] + procedure Setup; + + [TearDown] + procedure TearDown; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestSingleBookPrice; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestBasketContainsMyBooks; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestTotalBasketPriceSingleBook; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestTotalBasketPriceTwoofSameBook; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestTotalBasketPriceEmptyBasket; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestBasketWith2DifferentBooks; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestBasketWith3DifferentBooks; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestBasketWith4DifferentBooks; + + [Test] + [Ignore('Comment this line to perform this test')] + procedure TestBasketWith5DifferentBooks; + + [Test] + [Ignore('Comment this line to perform these test cases')] + [TestCase('basket 11223345', '11223345, 51.20')] + [TestCase('basket 112233445', '112233445, 55.60')] + [TestCase('basket 1122334455', '1122334455, 60.00')] + [TestCase('basket 11223344551', '11223344551, 68.00')] + [TestCase('basket 112233445512', '112233445512, 75.20')] + procedure SeveralBasketTestCases(aBasket: string; Expected: extended); + end; + +implementation +uses System.SysUtils; + +const MinDelta = 0.005; //cents + +procedure hpTests.Setup; +begin + fHP := NewHPBasket; +end; + +procedure hpTests.TearDown; +begin + fHP := nil; +end; + +procedure hpTests.TestSingleBookPrice; +begin + assert.AreEqual(8.0, Fhp.SingleBookPrice,'Incorrect single book price'); +end; + +procedure hpTests.TestBasketContainsMyBooks; +var MyBasket: string; +begin + MyBasket := '3'; //one copy of book three + fHP.Basket := MyBasket; + assert.AreEqual(MyBasket, fHP.Basket,'The basket isn''t correct'); +end; + +procedure hpTests.TestTotalBasketPriceSingleBook; +begin + fHP.Basket := '1'; //one copy of book one + assert.AreEqual(8.0, fHP.BasketTotal, MinDelta, 'Basket total incorrect'); +end; + +procedure hpTests.TestTotalBasketPriceTwoofSameBook; +begin + fHP.Basket := '22'; //two copies of book two + assert.AreEqual(16.0, fHP.BasketTotal, MinDelta, 'Basket total incorrect'); +end; + +procedure hpTests.TestTotalBasketPriceEmptyBasket; +begin + fHP.Basket := ''; + assert.AreEqual(0.0, fHP.BasketTotal, 'Total should be zero'); +end; + +procedure hpTests.TestBasketWith2DifferentBooks; +begin + fHP.Basket := '12'; //one copy of book one and one copy of book two + assert.AreEqual(15.2, fHP.BasketTotal, 'Total should be 15.2'); +end; + +procedure hpTests.TestBasketWith3DifferentBooks; +begin + fHP.Basket := '123'; //one copy of book 1, one copy of book 2, one copy of book 3 + assert.AreEqual(21.60, fHP.BasketTotal, 'Total should be 21.60'); +end; + +procedure hpTests.TestBasketWith4DifferentBooks; +begin + Fhp.Basket := '1234'; //one copy of book one, one copy book two, one copy of book three, and one copy of book four + assert.AreEqual(25.60,Fhp.BasketTotal, MinDelta,'Total should be 25.60'); +end; + +procedure hpTests.TestBasketWith5DifferentBooks; +begin + Fhp.Basket := '12345'; //one copy of book one, one copy book two, one copy of book three, one copy of book four, and one of book five + assert.AreEqual(30.00,Fhp.BasketTotal,MinDelta,'Total should be 30.00'); +end; + +procedure hpTests.SeveralBasketTestCases(aBasket: string; Expected: extended); +begin + Fhp.Basket := aBasket; + assert.AreEqual(Expected, Fhp.BasketTotal, MinDelta, format('Total should be %0.2f',[Expected])); +end; + +initialization + TDUnitX.RegisterTestFixture(hpTests); +end. From b6b91df467ed01437a5dcda6a19d86414c36417f Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Thu, 8 Dec 2016 12:17:18 -0500 Subject: [PATCH 2/6] Converted to book-store Was harry-potter, now is book-store --- .../BookStoreTests.dpr} | 6 +++--- .../BookStoreTests.dproj} | 8 ++++---- .../uBookStoreTests.pas} | 4 ++-- .../uBookStorerExample.pas} | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) rename exercises/{harry-potter/HarryPotterTests.dpr => book-store/BookStoreTests.dpr} (93%) rename exercises/{harry-potter/HarryPotterTests.dproj => book-store/BookStoreTests.dproj} (97%) rename exercises/{harry-potter/uHarryPotterTests.pas => book-store/uBookStoreTests.pas} (98%) rename exercises/{harry-potter/uHarryPotterExample.pas => book-store/uBookStorerExample.pas} (99%) diff --git a/exercises/harry-potter/HarryPotterTests.dpr b/exercises/book-store/BookStoreTests.dpr similarity index 93% rename from exercises/harry-potter/HarryPotterTests.dpr rename to exercises/book-store/BookStoreTests.dpr index 400e4303..361e9dca 100644 --- a/exercises/harry-potter/HarryPotterTests.dpr +++ b/exercises/book-store/BookStoreTests.dpr @@ -1,4 +1,4 @@ -program HarryPotterTests; +program BookStoreTests; {$IFNDEF TESTINSIGHT} {$APPTYPE CONSOLE} @@ -11,8 +11,8 @@ uses DUnitX.Loggers.Console, DUnitX.Loggers.Xml.NUnit, DUnitX.TestFramework, - uHarryPotterTests in 'uHarryPotterTests.pas', - uHarryPotter in 'uHarryPotter.pas'; + uBookStoreTests in 'uBookStoreTests.pas', + uBookStore in 'uBookStore.pas'; var runner : ITestRunner; diff --git a/exercises/harry-potter/HarryPotterTests.dproj b/exercises/book-store/BookStoreTests.dproj similarity index 97% rename from exercises/harry-potter/HarryPotterTests.dproj rename to exercises/book-store/BookStoreTests.dproj index babb77fe..4f25ec56 100644 --- a/exercises/harry-potter/HarryPotterTests.dproj +++ b/exercises/book-store/BookStoreTests.dproj @@ -3,7 +3,7 @@ {00833D4E-9C22-4AE8-8578-81B63523F423} 15.3 None - HarryPotterTests.dpr + BookStoreTests.dpr True Debug Win32 @@ -89,8 +89,8 @@ MainSource - - + + Cfg_2 Base @@ -159,7 +159,7 @@ - HarryPotterTests.dpr + BookStoreTests.dpr diff --git a/exercises/harry-potter/uHarryPotterTests.pas b/exercises/book-store/uBookStoreTests.pas similarity index 98% rename from exercises/harry-potter/uHarryPotterTests.pas rename to exercises/book-store/uBookStoreTests.pas index 551eedbd..ddafac92 100644 --- a/exercises/harry-potter/uHarryPotterTests.pas +++ b/exercises/book-store/uBookStoreTests.pas @@ -1,8 +1,8 @@ -unit uHarryPotterTests; +unit uBookStoreTests; interface uses - DUnitX.TestFramework, uHarryPotter; + DUnitX.TestFramework, uBookStore; type diff --git a/exercises/harry-potter/uHarryPotterExample.pas b/exercises/book-store/uBookStorerExample.pas similarity index 99% rename from exercises/harry-potter/uHarryPotterExample.pas rename to exercises/book-store/uBookStorerExample.pas index d1eb0969..39c2da31 100644 --- a/exercises/harry-potter/uHarryPotterExample.pas +++ b/exercises/book-store/uBookStorerExample.pas @@ -1,4 +1,4 @@ -unit uHarryPotter; +unit uBookStore; interface From 8c4f773c63bcd1e16cdabbb95484031e1a8fae59 Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Fri, 9 Dec 2016 10:37:27 -0500 Subject: [PATCH 3/6] Filename had an extra R --- .../book-store/{uBookStorerExample.pas => uBookStoreExample.pas} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename exercises/book-store/{uBookStorerExample.pas => uBookStoreExample.pas} (100%) diff --git a/exercises/book-store/uBookStorerExample.pas b/exercises/book-store/uBookStoreExample.pas similarity index 100% rename from exercises/book-store/uBookStorerExample.pas rename to exercises/book-store/uBookStoreExample.pas From 872ef40bc983c377f2835ab60a02ca2b33b6256b Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Tue, 13 Dec 2016 14:20:34 -0500 Subject: [PATCH 4/6] Cleaned up tests refactored down to a single test with multiple test cases to cover all the original tests. Removed residual hints of harry potter. Arrays are now passed into the basket. --- exercises/book-store/uBookStoreTests.pas | 147 +++++------------------ 1 file changed, 29 insertions(+), 118 deletions(-) diff --git a/exercises/book-store/uBookStoreTests.pas b/exercises/book-store/uBookStoreTests.pas index ddafac92..3190472b 100644 --- a/exercises/book-store/uBookStoreTests.pas +++ b/exercises/book-store/uBookStoreTests.pas @@ -2,141 +2,52 @@ interface uses - DUnitX.TestFramework, uBookStore; + DUnitX.TestFramework; type - [TestFixture] hpTests = class(TObject) private - fHP: Ihp; + class function ConvertStrToIntArray(aString: string): TArray; static; public - [Setup] - procedure Setup; - - [TearDown] - procedure TearDown; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestSingleBookPrice; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestBasketContainsMyBooks; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestTotalBasketPriceSingleBook; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestTotalBasketPriceTwoofSameBook; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestTotalBasketPriceEmptyBasket; - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestBasketWith2DifferentBooks; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestBasketWith3DifferentBooks; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestBasketWith4DifferentBooks; - - [Test] - [Ignore('Comment this line to perform this test')] - procedure TestBasketWith5DifferentBooks; - - [Test] - [Ignore('Comment this line to perform these test cases')] - [TestCase('basket 11223345', '11223345, 51.20')] - [TestCase('basket 112233445', '112233445, 55.60')] - [TestCase('basket 1122334455', '1122334455, 60.00')] - [TestCase('basket 11223344551', '11223344551, 68.00')] - [TestCase('basket 112233445512', '112233445512, 75.20')] - procedure SeveralBasketTestCases(aBasket: string; Expected: extended); + [TestCase('Test total basket price single book', '1, 8.0')] +// [TestCase('Test total basket Price two of same book', '2|2, 16.0')] +// [TestCase('Test total basket price empty basket', ', 0.0')] +// [TestCase('Test basket with two different books', '1|2, 15.2')] +// [TestCase('Test basket with three different books', '1|2|3, 21.6')] +// [TestCase('Test basket with four different books', '1|2|3|4, 25.6')] +// [TestCase('Test basket with five different books', '1|2|3|4|5, 30.0')] +// [TestCase('Test basket w/2 copies of books 1..3 and one copy of books 4 and 5', '1|1|2|2|3|3|4|5, 51.20')] +// [TestCase('Test basket w/2 copies of each book', '1|1|2|2|3|3|4|4|5|5, 60.00')] +// [TestCase('Test basket w/2 copies of each book plus one more copy of book 1', '1|1|2|2|3|3|4|4|5|5|1, 68.00')] +// [TestCase('Test basket w/2 copies of each book plus one more copy of books 1 and 2', '1|1|2|2|3|3|4|4|5|5|1|2, 75.20')] + procedure SeveralBasketTestCases(const aBasket: string; const Expected: extended); end; implementation -uses System.SysUtils; +uses System.SysUtils, uBookStore; const MinDelta = 0.005; //cents -procedure hpTests.Setup; -begin - fHP := NewHPBasket; -end; - -procedure hpTests.TearDown; -begin - fHP := nil; -end; - -procedure hpTests.TestSingleBookPrice; -begin - assert.AreEqual(8.0, Fhp.SingleBookPrice,'Incorrect single book price'); -end; - -procedure hpTests.TestBasketContainsMyBooks; -var MyBasket: string; -begin - MyBasket := '3'; //one copy of book three - fHP.Basket := MyBasket; - assert.AreEqual(MyBasket, fHP.Basket,'The basket isn''t correct'); -end; - -procedure hpTests.TestTotalBasketPriceSingleBook; -begin - fHP.Basket := '1'; //one copy of book one - assert.AreEqual(8.0, fHP.BasketTotal, MinDelta, 'Basket total incorrect'); -end; - -procedure hpTests.TestTotalBasketPriceTwoofSameBook; -begin - fHP.Basket := '22'; //two copies of book two - assert.AreEqual(16.0, fHP.BasketTotal, MinDelta, 'Basket total incorrect'); -end; - -procedure hpTests.TestTotalBasketPriceEmptyBasket; -begin - fHP.Basket := ''; - assert.AreEqual(0.0, fHP.BasketTotal, 'Total should be zero'); -end; - -procedure hpTests.TestBasketWith2DifferentBooks; -begin - fHP.Basket := '12'; //one copy of book one and one copy of book two - assert.AreEqual(15.2, fHP.BasketTotal, 'Total should be 15.2'); -end; - -procedure hpTests.TestBasketWith3DifferentBooks; -begin - fHP.Basket := '123'; //one copy of book 1, one copy of book 2, one copy of book 3 - assert.AreEqual(21.60, fHP.BasketTotal, 'Total should be 21.60'); -end; - -procedure hpTests.TestBasketWith4DifferentBooks; -begin - Fhp.Basket := '1234'; //one copy of book one, one copy book two, one copy of book three, and one copy of book four - assert.AreEqual(25.60,Fhp.BasketTotal, MinDelta,'Total should be 25.60'); -end; - -procedure hpTests.TestBasketWith5DifferentBooks; +class function hpTests.ConvertStrToIntArray(aString: string): TArray; +var splitStr: TArray; + i: integer; begin - Fhp.Basket := '12345'; //one copy of book one, one copy book two, one copy of book three, one copy of book four, and one of book five - assert.AreEqual(30.00,Fhp.BasketTotal,MinDelta,'Total should be 30.00'); + result := nil; + splitStr := aString.Split(['|']); + SetLength(result, length(splitStr)); + for i := Low(splitStr) to High(splitStr) do + result[i] := splitStr[i].ToInteger; end; -procedure hpTests.SeveralBasketTestCases(aBasket: string; Expected: extended); +procedure hpTests.SeveralBasketTestCases(const aBasket: string; const Expected: extended); +var Basket: TArray; + fBasket: IBasket; begin - Fhp.Basket := aBasket; - assert.AreEqual(Expected, Fhp.BasketTotal, MinDelta, format('Total should be %0.2f',[Expected])); + Basket := ConvertStrToIntArray(aBasket); + fBasket := NewBasket(Basket); + assert.AreEqual(Expected, FBasket.Total, MinDelta, format('Total should be %0.2f',[Expected])); end; initialization From 2aae819d760e102fba646895aeb2f035bb745b31 Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Tue, 13 Dec 2016 14:22:17 -0500 Subject: [PATCH 5/6] clean up Removed residual harry potterness. Removed unused methods and properties. Array of books (integers) is now expected instead of a string as input. --- exercises/book-store/uBookStoreExample.pas | 78 +++++++++------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/exercises/book-store/uBookStoreExample.pas b/exercises/book-store/uBookStoreExample.pas index 39c2da31..d3f28216 100644 --- a/exercises/book-store/uBookStoreExample.pas +++ b/exercises/book-store/uBookStoreExample.pas @@ -3,25 +3,18 @@ interface type - Ihp = interface(IInvokable) + IBasket = interface(IInvokable) ['{22B4BAF3-88E6-456D-9DE5-F6BAC743A655}'] - function BasketTotal:extended; - function NumberOfDifferentBooks(inStr : string):integer; - function GroupBasket:TArray; - function GetSingleBookPrice: extended; - function GetBasket: string; - procedure SetBasket(aValue: string); - property Basket: string read GetBasket write SetBasket; - property SingleBookPrice: extended read GetSingleBookPrice; + function Total:extended; end; -function NewHPBasket: Ihp; +function NewBasket(aBasket: TArray): IBasket; implementation uses System.SysUtils; const - hpBooks = '123456'; + seriesBooks = '12345'; cNumberOfBooks = 5; cDiscounts: array[1..cNumberOfBooks] of extended = (1.00, 0.95, @@ -30,63 +23,52 @@ implementation 0.75); type - Thp = class(TInterfacedObject, Ihp) + TBasket = class(TInterfacedObject, IBasket) private fSingleBookPrice: extended; fBasket: string; - Group: TArray; class function Head(inStr: string): string; static; class function Tail(inStr: string): string; static; - function GetSingleBookPrice: extended; + class function ConvertIntArrayToString(const aIntArray: TArray): string; static; function DiscountPercentage(inStr : string): extended; - procedure SetBasket(aValue: string); - function GetBasket: string; - public - function BasketTotal:extended; - function NumberOfDifferentBooks(inStr : string):integer; function GroupBasket:TArray; - property SingleBookPrice: extended read GetSingleBookPrice; - property Basket: string read GetBasket write SetBasket; - constructor Create; + function NumberOfDifferentBooks(inStr : string):integer; + public + function Total:extended; + constructor Create(aBasket: TArray); end; -function NewHPBasket: Ihp; +function NewBasket(aBasket: TArray): IBasket; begin - result := Thp.Create; + result := TBasket.Create(aBasket); end; -class function Thp.Head(inStr : string):string; +class function TBasket.Head(inStr : string):string; begin result := inStr.Remove(1); end; -class function Thp.Tail(inStr : string):string; +class function TBasket.Tail(inStr : string):string; begin result := inStr.Remove(0,1); end; -constructor Thp.Create; -begin - fSingleBookPrice := 8; - fBasket := ''; -end; - -function Thp.GetSingleBookPrice; +class function TBasket.ConvertIntArrayToString(const aIntArray: TArray): string; +var arrayItem: integer; begin - result := fSingleBookPrice; + result := ''; + if length(aIntArray) > 0 then + for arrayItem in aIntArray do + result := result + arrayItem.ToString; end; -procedure Thp.SetBasket(aValue: string); +constructor TBasket.Create(aBasket: TArray); begin - fBasket := aValue; -end; - -function Thp.GetBasket: string; -begin - result := fBasket; + fSingleBookPrice := 8; + fBasket := ConvertIntArrayToString(aBasket); end; -function Thp.GroupBasket:TArray; +function TBasket.GroupBasket:TArray; var lStrArray: TArray; wrkBasket: string; tmpStr : string; @@ -125,7 +107,7 @@ function Thp.GroupBasket:TArray; result := lStrArray; end; -function Thp.BasketTotal:extended; +function TBasket.Total:extended; var hpBook : char; totalBooks : integer; subBaskets : TArray; @@ -142,7 +124,7 @@ function Thp.BasketTotal:extended; end; end; -function Thp.DiscountPercentage(inStr : string):extended; +function TBasket.DiscountPercentage(inStr : string):extended; var numDiffBooks: integer; begin result := 1; @@ -150,12 +132,12 @@ function Thp.DiscountPercentage(inStr : string):extended; result := CDiscounts[numDiffBooks]; end; -function Thp.NumberOfDifferentBooks(inStr : string):integer; -var hpBook: char; +function TBasket.NumberOfDifferentBooks(inStr : string):integer; +var Book: char; begin result := 0; - for hpBook in hpBooks do - if inStr.Contains(hpBook) then + for Book in seriesBooks do + if inStr.Contains(Book) then inc(result); end; From c7fe9c84c2dd631aaaa05c18f10fdc5c6ec9a5c6 Mon Sep 17 00:00:00 2001 From: Ryan Potts Date: Mon, 19 Dec 2016 11:57:38 -0500 Subject: [PATCH 6/6] Added test case I had this test in my canonical data but not in the runner. --- exercises/book-store/uBookStoreTests.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/book-store/uBookStoreTests.pas b/exercises/book-store/uBookStoreTests.pas index 3190472b..cb6523c7 100644 --- a/exercises/book-store/uBookStoreTests.pas +++ b/exercises/book-store/uBookStoreTests.pas @@ -19,6 +19,7 @@ hpTests = class(TObject) // [TestCase('Test basket with four different books', '1|2|3|4, 25.6')] // [TestCase('Test basket with five different books', '1|2|3|4|5, 30.0')] // [TestCase('Test basket w/2 copies of books 1..3 and one copy of books 4 and 5', '1|1|2|2|3|3|4|5, 51.20')] +// [TestCase('Test basket w/2 copies of books 1..4 and one copy of book 5', '1|1|2|2|3|3|4|4|5, 55.60')] // [TestCase('Test basket w/2 copies of each book', '1|1|2|2|3|3|4|4|5|5, 60.00')] // [TestCase('Test basket w/2 copies of each book plus one more copy of book 1', '1|1|2|2|3|3|4|4|5|5|1, 68.00')] // [TestCase('Test basket w/2 copies of each book plus one more copy of books 1 and 2', '1|1|2|2|3|3|4|4|5|5|1|2, 75.20')]