The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,284 other followers

Archive for the ‘Agile’ Category

DUnit testing code that should raise a specific exception

Posted by jpluimers on 2021/02/17

A while back, I was writing some code to demonstrate a few inner workings of TInterfacedObject, interface reference counting and mixing object references with interface references.

One way to show this is through a test case that expects a certain exception to happen, but I forgot how to do that in DUnit. Luckily this pointed me on the right track: [WayBack] delphi – CheckException only accepts 0-parameter methods; how do I test that other methods throw exceptions? – Stack Overflow.

The solution shows that DUnit has had support for something similar as DUnitX: now has a WillRaiseAttribute to ease defining tests around code that should throw exceptions for a very long time (I think this was introduced around Delphi 2005).

You can do it in a property way:

unit InterfacedObjectTestCaseUnit;

interface

uses
  TestFramework;

type
  TDebuggableInterfacedObjectTestCase = class(TTestCase)
  published
    procedure System_TInterfacedObject_Free_Before_RefCount_Should_Raise_EInvalidPointer();
  end;

implementation

uses
  System.SysUtils,

procedure TInterfacedObjectTestCase.System_TInterfacedObject_Free_Before_RefCount_Should_Raise_EInvalidPointer();
var
  ObjectReference:    System.TInterfacedObject;
  InterfaceReference: IInterface;
begin
  ObjectReference    := System.TInterfacedObject.Create();
  InterfaceReference := ObjectReference;
  ExpectedException  := System.SysUtils.EInvalidPointer;
  ObjectReference.Free(); // this should raise an exception in System.TInterfacedObject.BeforeDestruction, as it checks the RefCount to be zero
  // the below is optional; should not be reached. If it is reached, it will fail earlier than the encompassing `RunTest` method would
  ExpectedException := nil; // or `StopExpectingException();`
end;

end.

or in a method way for an exception that happens in the current method:

procedure TInterfacedObjectTestCase.System_TInterfacedObject_Free_Before_RefCount_Should_Raise_EInvalidPointer();
var
  ObjectReference:    System.TInterfacedObject;
  InterfaceReference: IInterface;
begin
  ObjectReference    := System.TInterfacedObject.Create();
  InterfaceReference := ObjectReference;
  StartExpectingException(System.SysUtils.EInvalidPointer);
  ObjectReference.Free(); // this should raise an exception in System.TInterfacedObject.BeforeDestruction, as it checks the RefCount to be zero
  // the below is optional; should not be reached. If it is reached, it will fail earlier than the encompassing `RunTest` method would
  StopExpectingException();
end;

The alternative using CheckException that will raise earlier, but also tests the results of a complete method which also has to be parameterless:

procedure TDebuggableInterfacedObjectTestCase.System_TInterfacedObject_Free_Before_RefCount();
var
  ObjectReference:    System.TInterfacedObject;
  InterfaceReference: IInterface;
begin
  ObjectReference    := System.TInterfacedObject.Create();
  InterfaceReference := ObjectReference;
  ObjectReference.Free(); // this should raise an exception in System.TInterfacedObject.BeforeDestruction, as it checks the RefCount to be zero
end;

procedure TDebuggableInterfacedObjectTestCase.System_TInterfacedObject_Free_Before_RefCount_Should_Raise_EInvalidPointer_TTestMethod_Based();
begin
  CheckException(System_TInterfacedObject_Free_Before_RefCount, System.SysUtils.EInvalidPointer);
end;

So I wrote a class helper based on TProc that allows you to test an anonymous method which usually has more fine grained testing potential.

Because of type compatibility, you have to call the inherited version of CheckException inside the new one:

unit TestCaseHelperUnit;

interface

uses
  System.SysUtils,
  TestFramework;

type
  TTestCaseHelper = class helper for TTestCase
  public
    procedure CheckException(const AProc: TProc; const AExceptionClass: TClass; const msg: string = '');
  end;

implementation

type
  TTestCaseInvoker = class
  strict private
    FProc: TProc;
  public
    constructor Create(const AProc: TProc);
    procedure Execute();
  end;

{ TTestCaseInvoker }

constructor TTestCaseInvoker.Create(const AProc: TProc);
begin
  inherited Create();
  FProc := AProc;
end;

procedure TTestCaseInvoker.Execute();
begin
  if Assigned(FProc) then
    FProc();
end;

procedure TTestCaseHelper.CheckException(const AProc: TProc; const AExceptionClass: TClass; const msg: string = '');
var
  TestCaseInvoker: TTestCaseInvoker;
begin
  TestCaseInvoker := TTestCaseInvoker.Create(AProc);
  try
    inherited CheckException(TestCaseInvoker.Execute, AExceptionClass, msg); // `inherited`, to avoid stack overflow because `TProc` is compatible with `TTestMethod`
  finally
    TestCaseInvoker.Free();
  end;
end;

end.

The test then becomes this:

procedure TDebuggableInterfacedObjectTestCase.System_TInterfacedObject_Free_Before_RefCount_Should_Raise_EInvalidPointer_TProc_Based();
var
  ObjectReference:    System.TInterfacedObject;
  InterfaceReference: IInterface;
begin
  ObjectReference    := System.TInterfacedObject.Create();
  InterfaceReference := ObjectReference;
  CheckException(procedure ()
  begin
    ObjectReference.Free(); // this should raise an exception in System.TInterfacedObject.BeforeDestruction, as it checks the RefCount to be zero
  end,
  System.SysUtils.EInvalidPointer);
end;

DUnit code snippets

Read the rest of this entry »

Posted in Agile, Conference Topics, Conferences, Delphi, Development, Event, Software Development, Unit Testing | Leave a Comment »

Twitter @Nick_Craver: “I’ve talked with so, so many new devs over the years and far too many are afraid to try because they’re afraid to fail. So do me a favor, share your failures […]”

Posted by jpluimers on 2021/02/04

Every now and then it is good to read back this [WayBack] thread by @Nick_Craver: “

I’ve talked with so, so many new devs over the years and far too many are afraid to try because they’re afraid to fafavor, share your failures.

So do me a favor, share your failures. Not just the successes. It’s not just about learning from them. Sometimes it’s just about people knowing they happen.

Reminder: you see the successes people are proud of and want to shout from the rooftops for all to see. Far, far fewer people share all the failures leading up to those successes. Yet those missteps are almost always far more numerous.

Hi, I’m a dev. I’ve caused more production outages that I can count. I’ve deleted a production database by accident. I’ve missed hundreds of bugs in code reviews. I try my best. I try to not repeat mistakes. It still happens sometimes. I still think my impact has been a net good.

[…]”

The thing about mistakes is that they do happen, and we need to learn from them. Almost always, it is useless to blame, but do your best to prevent them from happening again by doing blameless post-mortem.

We do however need to become better engineers, so this thread is relevant as well, because the impact of some is not been a net good:

[Cached] WayBack: thread by @www_ora_tion_ca: “This is wildly disingenuous, I speak as a flight instructor and major IT incident investigator. Modern software authors have the professional discipline of a cute puppy in comparison to aviation practitioners. […]”. quoting [WayBack] Alex Stamos on Twitter: “I agree with Chris. This is the kind of thinking that leads to “Why can’t we just have building codes for software? It worked to protect against earthquakes and fire!” Earthquakes and fire aren’t conscious adversaries. Try writing a standards document on how to win at chess.”

My biggest faults:

Read the rest of this entry »

Posted in Agile, Code Quality, Development, Software Development | Leave a Comment »

Client: “How much time will it take to finish this job?”- Your Ex-Waifu

Posted by jpluimers on 2020/09/24

From Client: “How much time will it take to finish this job?”- Your Ex-Waifu

Client: “How much time will it take to finish this job?”
Me: “About six weeks”
Client: “You have two weeks.”
Me: “OK, I’ll try to explain myself better.”

–jeroen

Video: https://www.tumblr.com/video/newandimprovedbeef/170394974576/500/

Posted in Agile, Development, LifeHacker, Power User, Software Development | Leave a Comment »

7 Rules for Creativity Managers – YouTube

Posted by jpluimers on 2020/09/18

Interesting video explaining there is a lot of work to do around me, meaning I probably need more in stead of less people around me (:

  • Nurture diversity: Creativity managers dislike brains being the same.
  • Create markets: Creativity managers favor coopetition in networks.
  • Rely on merits: Creativity managers embrace networks and gameplay.
  • Make no predictions: Creativity managers keep many options open.
  • Update the workplace: Creativity managers work the environment.
  • Change constraints: Creativity managers optimize for exploration.
  • Open boundaries: Creativity managers connect instead of protect.

Via [WayBack] 7 Rules for Creativity Managers – Marjan Venema – Google+ (who is a great coach).

–jeroen

Read the rest of this entry »

Posted in Agile, Development, LifeHacker, Power User | Leave a Comment »

The iron triangle of planning | Atlassian

Posted by jpluimers on 2020/09/01

The traditional iron triangle of planning is turned up-side down when being agile: [WayBack] The iron triangle of planning | Atlassian.

On the left, the traditional triangle, on the right the agile one.

Via: [WayBack] The iron triangle of planning The Agile Coach – Marjan Venema – Google+

–jeroen

Posted in Agile, Development, Software Development | Leave a Comment »

 
%d bloggers like this: