Recent

Author Topic: Right way to write tests  (Read 11230 times)

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Right way to write tests
« Reply #15 on: June 27, 2017, 08:16:30 am »
@Mr.Madguy, Thanks.
One more question. How to check expected exception? What is common way in FPC?
Yeah, my unit tests don't check for expected ones - they just report exceptions, if they happen, and treat such cases as failed tests. But if I would need it - it indeed would be something like this:
Code: Pascal  [Select][+][-]
  1. unit TestMain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   TCallback = procedure of object;
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Label1: TLabel;
  17.     Label2: TLabel;
  18.     Label3: TLabel;
  19.     procedure FormCreate(Sender: TObject);
  20.   private
  21.     { private declarations }
  22.   public
  23.     { public declarations }
  24.     procedure MyCallback;
  25.     function CheckException(ACallback:TCallback;AExceptionClass:ExceptClass;const AMessage:String):Boolean;
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. const
  36.   BooleanToString:array[Boolean] of String = (
  37.     'False',
  38.     'True'
  39.   );
  40.  
  41. procedure TForm1.FormCreate(Sender: TObject);
  42. begin
  43.   Label1.Caption := BooleanToString[CheckException(@MyCallback, EAbort, 'This is test')];
  44.   Label2.Caption := BooleanToString[CheckException(@MyCallback, EZeroDivide, 'This is test')];
  45.   Label3.Caption := BooleanToString[CheckException(@MyCallback, EAbort, 'Some other message')];
  46. end;
  47.  
  48. procedure TForm1.MyCallback;
  49. begin
  50.   raise EAbort.Create('This is test');
  51. end;
  52.  
  53. function TForm1.CheckException(ACallback:TCallback;AExceptionClass:ExceptClass;const AMessage:String):Boolean;
  54. begin
  55.   try
  56.     Result := False;
  57.     ACallback;
  58.   except
  59.     on E:Exception do begin
  60.       if (E is AExceptionClass) and (E.Message = AMessage) then begin
  61.         Result := True;
  62.       end;
  63.     end;
  64.   end;
  65. end;
  66.  
  67. end.
  68.  
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

jc99

  • Hero Member
  • *****
  • Posts: 553
    • My private Site
Re: Right way to write tests
« Reply #16 on: June 27, 2017, 11:47:40 am »
And mostly these are the hard ones, (I mean find the boundaries of your method and have a good exception-handling)

Found the flaw in my function ?

@Lele: [...]
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

_N_

  • New Member
  • *
  • Posts: 33
Re: Right way to write tests
« Reply #17 on: June 27, 2017, 07:57:21 pm »
Thank you, guys, very much! Especially for examples))

jc99

  • Hero Member
  • *****
  • Posts: 553
    • My private Site
Re: Right way to write tests
« Reply #18 on: July 03, 2017, 01:46:44 pm »
Found the flaw in my function ?
Here is the solution to my question:
The problem is in the abs()-function that not always gives a positive result.
e.G: in smallint (2-Byte) there is no positive number to -32768 because the highest positive is 32767 so the result of abs(smallint(-32768)) is -32768 !!
the same goes with integer (4-byte) there is no positive number to -‭2147483648‬ because the highest positive is ‭21474836487 so the result of abs(-‭2147483648‬) is -‭2147483648‬ !
 -‭2147483648‬ mod 23 is -6

to circumvent this the function has to look like this:
Code: Pascal  [Select][+][-]
  1. function TMyClass.hash(aValue:integer):integer;
  2.  
  3. begin
  4.   result := abs(aValue mod 23);
  5. end;
the modulo function gives a result of -22 to +22 now the abs function has no problem to give a positive number from 0..22

BTW if you put this function in a helper-class the original class has no access. So its an even bigger mistake (but would result in a compiler-error).


OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

_N_

  • New Member
  • *
  • Posts: 33
Re: Right way to write tests
« Reply #19 on: July 18, 2017, 09:28:51 pm »
Sorry for asking after delay, but I run into some troubles.
I decided to use FPCUnit. But I cannot find enough information or docs for it.

1) When I created test application from samples and tried to run it, I got:
Code: Pascal  [Select][+][-]
  1. fpcunitproject1.lpr(6,22) Fatal: Cannot find GuiTestRunner used by FPCUnitProject1.
That's looks strange, sample doesn't work....
I use: FPC 3.0.2 and Lazarus 1.6.4+dfsg-1, 64 bit, Ubuntu 17.04
Well, I am fine with console version, but still...

2) I want to have separate test suite for each modules group (simpler - a subfolder of project). Also I want to run all tests.
How can I reach it?
For now I have error:
Code: Pascal  [Select][+][-]
  1. testregistrator.pas(18,42) Error: Incompatible type for arg no. 2: Got "Class Of TGroupXTestSuite", expected "TTest"

I cannot use RegisterTest for TestSite, despite tutorial which I googled says I can (maybe it outdated a bit ?)
My code:

Code: Pascal  [Select][+][-]
  1. // The application file is autogenerated, I only added TestRegistrator in uses section

Code: Pascal  [Select][+][-]
  1. unit TestRegistrator;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, fpcunit, testutils, testregistry,
  9.   GroupXTestSuite;
  10.  
  11. implementation
  12.  
  13. procedure RegisterAllTests();
  14. begin
  15.   // TTestSuite -> TTest -> TObject
  16.   // TTestCase -> TAssert -> TTest -> TObject
  17.   // procedure RegisterTest(ASuitePath: String; ATest: TTest); overload;
  18.   RegisterTest('GroupX', TGroupXTestSuite); // <---- Error is here.
  19. end;
  20.  
  21. initialization
  22.   RegisterAllTests();
  23.  
  24. end.
  25.  

Code: Pascal  [Select][+][-]
  1. unit TGroupXTestSuite;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, fpcunit, testregistry,
  9.   SomeTestCase;
  10.  
  11. type
  12.  
  13.   TGroupXTestSuite = class(TTestSuite)
  14.   published
  15.     procedure RegisterSuiteTests();
  16.   end;
  17.  
  18. implementation
  19.  
  20. procedure TGroupXTestSuite.RegisterSuiteTests();
  21. begin
  22.   RegisterTest(TSomeTestCase);
  23. end;
  24.  
  25. end.
  26.  

Code: Pascal  [Select][+][-]
  1. unit TSomeTestCase;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, fpcunit, testutils, testregistry;
  9.  
  10. type
  11.  
  12.   { TTestCase1 }
  13.  
  14.   TSomeTestCase = class (TTestCase)
  15.   protected
  16.     procedure SetUp(); override;
  17.     procedure TearDown(); override;
  18.   published
  19.     procedure TestHookUp;
  20.   end;
  21.  
  22. implementation
  23.  
  24. procedure TSomeTestCase.SetUp();
  25. begin
  26.  
  27. end;
  28.  
  29. procedure TSomeTestCase.TearDown();
  30. begin
  31.  
  32. end;
  33.  
  34. procedure TSomeTestCase.TestHookUp;
  35. begin
  36.   Fail('Write your own test');
  37. end;
  38.  
  39. initialization
  40.  
  41. end.
  42.  
                           
« Last Edit: July 18, 2017, 09:32:54 pm by _N_ »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Right way to write tests
« Reply #20 on: July 18, 2017, 09:44:53 pm »
Sorry for asking after delay, but I run into some troubles.
I decided to use FPCUnit. But I cannot find enough information or docs for it.

1) When I created test application from samples and tried to run it, I got:
Code: Pascal  [Select][+][-]
  1. fpcunitproject1.lpr(6,22) Fatal: Cannot find GuiTestRunner used by FPCUnitProject1.
             
a search in the forums might have revealed the answer http://forum.lazarus.freepascal.org/index.php/topic,37496.0.html
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

_N_

  • New Member
  • *
  • Posts: 33
Re: Right way to write tests
« Reply #21 on: July 19, 2017, 07:51:13 pm »
@taazz thank you. I indeed had to search before asking despite the second problem is more important...

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Right way to write tests
« Reply #22 on: July 19, 2017, 08:05:57 pm »
@taazz thank you. I indeed had to search before asking despite the second problem is more important...
As far as I am aware the second problem should not exists if the first problem is solved correctly then you should be able to call the test registration procedures. Do you have a simple test case that has the problem? especially after the 1st problem is correctly solved. In the mean time find attached an empty test project that you can use a starting point. Open it up in lazarus an use save as to rename it to what ever you need.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

_N_

  • New Member
  • *
  • Posts: 33
Re: Right way to write tests
« Reply #23 on: July 19, 2017, 08:40:25 pm »
@taazz your sample works perfectly. Thanks.
Maybe I will switch to GUI version, but still curios (and want implement) test suites.
I see TTestSuite class, but have no idea how to use it, register tests in it and so on. What I googled, that I have to just register tests like:
Code: Pascal  [Select][+][-]
  1.  RegisterTest('Level1.Level2', TTestCase2);
If it works (and it does) what for TTestSuite exists? Should I use it at all or it is just internal stuff? That confuses.
« Last Edit: July 19, 2017, 08:42:05 pm by _N_ »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Right way to write tests
« Reply #24 on: July 19, 2017, 08:51:14 pm »
@taazz your sample works perfectly. Thanks.
Maybe I will switch to GUI version, but still curios (and want implement) test suites.
I see TTestSuite class, but have no idea how to use it, register tests in it and so on. What I googled, that I have to just register tests like:
Code: Pascal  [Select][+][-]
  1.  RegisterTest('Level1.Level2', TTestCase2);
If it works (and it does) what for TTestSuite exists? Should I use it at all or it is just internal stuff? That confuses.
the name TTestcase is a bit misleading, when it comes to the registration procedures anything that inherits from TTestCase consider it a test suite.
Ok I was thinking something else TTesSuite is used internally when ever you define a name for it eg
Code: Pascal  [Select][+][-]
  1. RegisterTest('MyAwesomeControl', TTestCase2);
will create automatically a ttestsuite with the title my MyAwesomeControl as far as I know the title becomes a key and multiple test cases can be registered from different files and at different times.
« Last Edit: July 19, 2017, 08:56:25 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

_N_

  • New Member
  • *
  • Posts: 33
Re: Right way to write tests
« Reply #25 on: July 19, 2017, 09:06:38 pm »
@taazz Thank you very very much for clarification!

 

TinyPortal © 2005-2018