Coder Social home page Coder Social logo

dataset-generator's People

Contributors

bogdanpolak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

dataset-generator's Issues

Required support for TBCDField

Can't generate mock data in TFDMemTable for TBCDField.

  1. No data for ftBCD
  2. Incorrect AddField: FieldDefs.Add('Price', ftBCD, 2); (two size parameters)

GenerateFunction code is invalid using TClientDataSet

  • WHEN: Generator.DataSetType:= dstClientDataSet;
  • THEN: actualCode := Generator.GenFunction; actualCode is not compiling (TClientDataSet can't be assigned to TFDMemTable):
function CreateDataSet (aOwner: TComponent): TDataSet;
var
  ds: TFDMemTable;
begin
  ds := TClientDataSet.Create(AOwner);

Refactoring

  • Refactor method: TDSGenerator.GenFunction not to use Execute (string lists)

TDSGenerator - make it more testable

Remove protected methods from TDSGenerator (exposed for unit tests) and delete class TDSGeneratorUnderTest

Refine the possibility of decomposition this item into several smaller Stories

Refactor dataset unit tests

  1. Remove Test.Common.TTestGenerate
    • tests are too difficult to read because of the reusability
  2. Refactor component class name: TGenerateDataSet
  3. Rename test classes and test units
  4. Add method constructing dataset: ds := GivenSampleDataSet (aOwner)
  5. Add fOwner: TComponent to manage dataset memory
  6. Add helper: TAssert.AreStringListsEqual (expectedCode, generatedCode) - comparing by lines
  7. Add new testing unit TestGenerator

New Append Mode - amAppendRowArray

  TAppendMode = (amMultilineAppend, amSinglelineAppend, amAppendRows);

amAppendRows mode:

  ds.AppendRows([
    [1, 'Team integration', EncodeDate(2019, 09, 16), 1.2, 1200],
    [2, 'Progress retrospective', Null, Null, 950]
  ]);

Generated long string literals divided by whole words

Improve divide long string litterals (76+ chars):

  • The algorithm should divide whole worlds (line lenght less or equal to 76 chars).

Example:

Should:

FieldByName('Description').Value :=
  'Covers Dependency Injection, you''ll learn about Constructor Injection' +
  ', Property Injection, and Method Injection and about the right and' +
  ' wrong way to use it';

Now:

FieldByName('Description').Value :=
  'Covers Dependency Injection, you''ll learn about Constructor Injection, Pro' +
  'perty Injection, and Method Injection and about the right andwrong way to u' +
  'se it';

Remove helper TStrings

Refactor code in src folder info one unit to allow easy copy to other Delphi projects

Add Filter property

aGenerator := TDSGenerator.Create(fOwner);
aGenerator.DataSet := fdqOrdesInYear;
aGenerator.Filter := Format(
    'ShipVia = %d and EmployeeID = %d and OrderDate >= %d and OrderDate < %d',
    [1, 8, Round(EncodeDate(1998,01,01)), Round(EncodeDate(1998,01,31)+1)]);
aGenerator.Execute;

Change method name

  1. No changes:
unit {UnitName};

default: fUnitName = uSampleDataSet
2) factory method interface declaration:

function GivienDataSet (aOwner: TComponent): TDataSet;
  1. factory method implementation:
function GivienDataSet  (aOwner: TComponent): TDataSet;
begin

Save to file has incorrect names: (1) file name and (2) unit name

GenerateAndSaveToFile is generating invalid file: unit name is default uSampleDataSet and file name is provided though parameter doesn't changes unit name

Method GenerateAndSaveToFile call:

TDSGenerator.GenerateAndSaveToFile(aDataSet, 
    'FakeDataSet.Historical.pas');

generates:

unit uSampleDataSet;

but expected is:

unit FakeDataSet.Historical;

[New sample] OrderView with IncomeImpact

Build new sample project with TOrdersView:

function TOrdersView.SelectMonth;
var
  aDate: TDateTime;
begin
  aDate := fMonthSelector.Execute;
  aDataSet := fDataSetFactory.ConstructSelectDataset(
    SQL_SELECT_CustomerOrders_FromOneMonth, 
    [YearOf(aDate), MonthOf(aDate)] );
  SetMasterDataset(aDataSet);
end;

And test ImpactSales with Fake dataset:

procedure TestOrdersView.Setup;
begin
  fOwner := TComponent.Create;
  fOrderModelMock := TMock<IOrdersModel>.Create;
  fOrdersView := TOrdersView.Create(fOrderModelMock);
  // ...
end;

procedure TestOrdersView.Test_CalculateCurrentImpact;
var
  aFakeOrdersDataSet: TDataSet;
  actualImpact: Extended;
begin
  aFakeOrdersDataSet := CreateDataSet(fOwner);
  fOrdersView.SetMasterDataset(aFakeOrdersDataSet);
  
  actualImpact := fOrdersView.GetCurrentImpact;

  Assert.AreEqual(0.054, actualImpact, 0.0000001);
end;

Scorecards Demo - calculate score

Implement:

  • Score calculation for one order based on Total Order Value and Product Category
  • Score range [0 .. 100]
  • Display in TMemo

Related to: #39

Remove protected methods from TDSGenerator

Remove protected methods from TDSGenerator (exposed for unit tests) and delete class TDSGeneratorUnderTest

Refine the possibility of decomposition this item into several smaller Stories

Change format of the code appending data

Should be:

  with ds do
  begin
    Append;
    FieldByName('ISBN').Value := '978-0321127426';
    FieldByName('Title').Value := 'Patterns of Enterprise Application Architecture';
    Post;
  end;
  with ds do
  begin
    Append;
    FieldByName('ISBN').Value := '978-1849689121';
    FieldByName('Title').Value := 
      'Applied Architecture Patterns on the Microsoft Platform (Second Edit'+
      'ion)';
    Post;
  end;

Now is:

  with ds do
  begin
    Append;
      FieldByName('ISBN').Value := '978-0321127426';
      FieldByName('Title').Value := 'Patterns of Enterprise Application Architecture';
    Post;
    Append;
      FieldByName('ISBN').Value := '978-1849689121';
      FieldByName('Title').Value := 
        'Applied Architecture Patterns on the Microsoft Platform (Second Edit'+
        'ion)';
    Post;
  end;

[doc] Add sample to main README

Sample

function CreateDataSet (AOwner: TComponent): Data.DB.TDataSet;
var
  ds: TFDMemTable;
begin
  ds := TFDMemTable.Create(AOwner);
  with ds do
  begin
    FieldDefs.Add('id', ftInteger);
    FieldDefs.Add('text1', ftWideString, 30);
    FieldDefs.Add('date1', ftDate);
    FieldDefs.Add('float1', ftFloat);
    FieldDefs.Add('currency1', ftCurrency);
    CreateDataSet;
    AppendRecord([1, 'Ala ma kota', EncodeDate(2019, 09, 16), 1.2, 1200]);
    AppendRecord([2, 'Ala ma kota', System.Variants.Null, Null, 950]);
  end;
  ds.First;
  Result := ds;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Generator: TGenerateDataSetCode;
begin
  Generator := TGenerateDataSetCode.Create(Self);
  Generator.DataSet := CreateDataSet(Generator);
  GenerateDataSetCode.Execute;
  Memo1.Lines := GenerateDataSetCode.Code;
  Generator.Free;
end;

Memo1 content

ds := TFDMemTable.Create(AOwner);
with ds do
begin
  FieldDefs.Add(''id'', ftInteger);
  FieldDefs.Add(''text1'', ftWideString, 30);
  FieldDefs.Add(''date1'', ftDate);
  FieldDefs.Add(''float1'', ftFloat);
  FieldDefs.Add(''currency1'', ftCurrency);
  CreateDataSet;
end;
with ds do
begin
  Append;
  FieldByName(''id'').Value := 1;
  FieldByName(''text1'').Value := ''Ala ma kota'';
  FieldByName(''date1'').Value := EncodeDate(2019,9,16);
  FieldByName(''float1'').Value := 1.2;
  FieldByName(''currency1'').Value := 1200;
  Post;
end;
with ds do
begin
  Append;
  FieldByName(''id'').Value := 2;
  FieldByName(''text1'').Value := ''Ala ma kota'';
  FieldByName(''currency1'').Value := 950;
  Post;
end;

Add Header and Footer

New properties

Add properties to component TGenerateDataSetCode

  • `Header: TStrings read FHeader write FHeader;
  • Footer as above

Option AppendMode - single-line AppendRecords / classic multiline Appends

Add option:

type
  TAppendMode = (amMultilineAppends, amSinglelineAppends);

  TDSGenerator = class (TComponent)
    property AppendMode: TAppendMode ... ;

In the first mode component is generating same code as before, but in new mode (amSinglelineAppends) it should generate single AppendRecord method for the whole data row:

with ds do
begin
  AppendRecord ([ 1, ''Ala ma kota'', EncodeDate(2019,9,16), 1.2, 1200]);
  AppendRecord ([2, ''Ala ma kota'', Null, 950]);
  Post;
end;

Option GenerateCode, property Code

Option

type
  TGeneratorMode = genAll (default), genStructure, genAppend);

  TDSGenerator = class(TComponent)
  // ...
    property GeneratorMode: TGeneratorMode ...;

One Code property
Change:

//    property CodeWithStructure: TStrings read FCodeWithStructue;
//    property CodeWithAppendData: TStrings read FCodeWithAppendData;
    property Code: TStrings read FCode

has influence on methods:

  • GenerateAsString
  • GenerateAsArray

Generate dataset code to file

Add method generating:

  1. Generate whole unit (PAS) code to stream (file)
    • GenerateAndSaveToStream (ds, stream)
    • GenerateAndSaveToFile (ds, fileName)

Rename unit to `MemoryDataSetGenerator.pas`

  1. Rename unit
  2. Rename project to Memory DataSet Generator
  3. Update Supported Delphi version to 11.2
  4. Update unit header title and project link
{* ------------------------------------------------------------------------
 * ♥
 * ♥ DataSet to Delphi Code (create TFDMemTable with the data)
 * ♥
 * Component: TDSGenerator
 * Project: https://github.com/bogdanpolak/datasetToDelphiCode
 * ------------------------------------------------------------------------ }

Pack Append Section - remove with

Remove with sections:

ds.Append;
ds.FieldByName(''id'').Value := 1;
ds.FieldByName(''text1'').Value := ''Alice has a cat';
ds.Post;
ds.Append;
ds.FieldByName(''id'').Value := 2;
ds.FieldByName(''text1'').Value := ''Cat has a'';
ds.Post;

Split generated code into two parts: structure creation and data insertion

Change property Code: TStrings read FCode; into:

 property CodeWithStructure: TStrings read FCode;
 property CodeWithAppendData: TStrings read FCode;
  1. Update unit tests
  2. Update the component
  3. Update a documentation

New documentation

Structure creation = CodeWithStructure

ds := TFDMemTable.Create(AOwner);
with ds do
begin
  FieldDefs.Add(''id'', ftInteger);
  FieldDefs.Add(''text1'', ftWideString, 30);
  FieldDefs.Add(''date1'', ftDate);
  FieldDefs.Add(''float1'', ftFloat);
  FieldDefs.Add(''currency1'', ftCurrency);
  CreateDataSet;
end;

Data insertion = CodeWithAppendData :

with ds do
begin
  Append;
  FieldByName(''id'').Value := 1;
  FieldByName(''text1'').Value := ''Ala ma kota'';
  FieldByName(''date1'').Value := EncodeDate(2019,9,16);
  FieldByName(''float1'').Value := 1.2;
  FieldByName(''currency1'').Value := 1200;
  Post;
  Append;
  FieldByName(''id'').Value := 2;
  FieldByName(''text1'').Value := ''Ala ma kota'';
  FieldByName(''currency1'').Value := 950;
  Post;
end;

Updated documentation to ver 1.4

Update items:

  1. Add section "Fakes vs mocks"
  2. MaxRows property
    • default = 100
  3. Update docs and samples to - [Pack Append Section - remove with]

Add property IndentationText: string

Code Generator TGenerateDataSetCode should have property IndentationText: string

Add property IndentationText
Given developer willing to set up indentation text for each line of the generated code
When ...
And ..
Then ...

Investigate: TGeneratorOption record

Investigate:

TGeneratorOptions = record
  IndentationText: String;
  DataSetType: TDataSetType;
  AppendMode: TAppendMode;
  MaxRows: Integer;
end;

and overloaded methods:

GenerateAsString(ds: TDataSet; const options: TGeneratorOptions): string;
GenerateAsArray(ds: TDataSet; const options: TGeneratorOptions): TArray<String>;
GenerateAndSaveToStream(ds: TDataSet; aStream: TStream; const options: TGeneratorOptions);
GenerateAndSaveToFile(ds: TDataSet; const aFileName: string; const options: TGeneratorOptions);
GenerateAndSaveClipboard(ds: TDataSet; const options: TGeneratorOptions);

Fix warning for generator property UnitName

Warning: [dcc32 Warning] Comp.Generator.DataSetCode.pas(71): W1009 Redeclaration of 'UnitName' hides a member in the base class in:

type
  TDSGenerator = class(TComponent)
    ...
    property UnitName: string read fUnitName write fUnitName;
  end;

Rename fUnitName -> fNameOfUnit
Serach for UnitName in tests and samples (warning code can be compiled even with partial rename)

[Doc] Signature and Version in the component code

Add signature and register component version in this.

Discussion: Please suggest signature templete (how to automaticly verify version?). Maybe version can be write down in component const section?

Add Gen_UnitGeneration & refactor option

Update function Gen_UnitHeader according to Proxy generator changes:

function TDataProxyGenerator.Gen_UnitHeader: string;
begin
  Result :=
    {} 'unit Proxy.' + fObjectName + ';'+ sLineBreak +
    {} sLineBreak;
end;

Refactor option TGeneratorMode to:

  TGeneratorMode = (genStructure, genAppend, genFunction, genUnit);

with default value = genFunction

UPDATE DOC

Improve generated data for string literals

Divide long string litterals into chunks, each 76 characters lenght. Algotrhim shuld divide whole worlds (line lenght less or equal to 76 chars).
Should be:

    FieldByName('Description').Value :=
      'Covers Dependency Injection, you''ll learn about Constructor Injection' +
      ', Property Injection, and Method Injection and about the right and' +
      ' wrong way to use it';

Redesign property IdentationText usage

Info

Property should be used for each indentation. Requires #10.

Test

  • Test with one tab indentation

Warning! Could require big refactoring in test code (templates with indentation: use right arrow char (→ ◇ ↩ ↦ ▷)

Rename projects and folders

  1. folder: generators => sample
  2. project: generators/Dataset2Code.dproj => sample/DemoGenerateDataSet.dproj
  3. project: tests/DUnitxDatasetToCode.dproj => tests/TestDSGenerator.dproj

Update documentation to version 1.3 features

Update main README file and samples:

  1. Describe usage scenario (unit tests)
  2. TDSGenerator component usage
  3. Methods:
    • GenerateAsString
    • GenerateAsArray
    • GenerateAndSaveToStream / GenerateAndSaveToFile
    • GenerateAndSaveToClipboard
  4. Options
    • IdentationText
    • GenerateCode
    • AppendMode
    • GenerateDataSet
  5. Component Class TDSGenerator

Update project sample

not delivered in current version (1.2) where it was requested

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.