comp.lang.ada
 help / color / mirror / Atom feed
* Testing a package's internal details.
@ 2010-03-05  0:57 Peter C. Chapin
  2010-03-05  6:41 ` Niklas Holsti
  2010-03-05 11:31 ` Stephen Leake
  0 siblings, 2 replies; 4+ messages in thread
From: Peter C. Chapin @ 2010-03-05  0:57 UTC (permalink / raw)


A situation has come up for me and I'm wondering what the "best" way is to
handle it. Here are the particulars...

I have a package that models a single abstract object. The specification
declares the operations that are allowed on the object. I would like to write
some test procedures that can be used to exercise my implementation. Using a
test program that exists outside the package, I can treat the package like a
black box and call the public interface to the package during my tests. That
is fine.

However, I'd also like to write some test procedures that independently
exercise certain internal facilities without being constrained by the public
interface. Those procedures are not really part of the abstraction I'm trying
to present and I don't really want normal client code to call them. I do want
the test program to call them, of course.

Is there a "best practice" in this area that I should be following? At first I
thought I might be able to make my test procedures part of a child package
but that doesn't work because a child package has no access to the internal
part of the parent's body (true?). I suppose I could declare the test
procedures in the private part of the parent's specification and then provide
a child with a public procedure that just calls the parent's private test
procedure. Something like

package Test_Me is
  -- ...
private
  procedure Internal_Tests;
end Test_Me;

package Test_Me.Tester is
  procedure Do_Tests;  -- Call Test_Me.Internal_Tests (+ other stuff)
end Test_Me.Tester;

Is there a more elegant or appropriate way?

Thanks!

Peter




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Testing a package's internal details.
  2010-03-05  0:57 Testing a package's internal details Peter C. Chapin
@ 2010-03-05  6:41 ` Niklas Holsti
  2010-03-05 11:25   ` Peter C. Chapin
  2010-03-05 11:31 ` Stephen Leake
  1 sibling, 1 reply; 4+ messages in thread
From: Niklas Holsti @ 2010-03-05  6:41 UTC (permalink / raw)


Peter C. Chapin wrote:
> A situation has come up for me and I'm wondering what the "best" way is to
> handle it. Here are the particulars...
> 
> I have a package that models a single abstract object. The specification
> declares the operations that are allowed on the object. I would like to write
> some test procedures that can be used to exercise my implementation. Using a
> test program that exists outside the package, I can treat the package like a
> black box and call the public interface to the package during my tests. That
> is fine.
> 
> However, I'd also like to write some test procedures that independently
> exercise certain internal facilities without being constrained by the public
> interface. Those procedures are not really part of the abstraction I'm trying
> to present and I don't really want normal client code to call them. I do want
> the test program to call them, of course.
> 
> Is there a "best practice" in this area that I should be following? At first I
> thought I might be able to make my test procedures part of a child package
> but that doesn't work because a child package has no access to the internal
> part of the parent's body (true?). I suppose I could declare the test
> procedures in the private part of the parent's specification and then provide
> a child with a public procedure that just calls the parent's private test
> procedure. Something like
> 
> package Test_Me is
>   -- ...
> private
>   procedure Internal_Tests;
> end Test_Me;
> 
> package Test_Me.Tester is
>   procedure Do_Tests;  -- Call Test_Me.Internal_Tests (+ other stuff)
> end Test_Me.Tester;
> 
> Is there a more elegant or appropriate way?

I've seen two ways to do this:

- First way: As you suggest, above, but make the test procedure 
(Internal_Tests) be separately implemented ("is separate" as the body). 
This at least removes the code for the internal tests into a separate 
file. By juggling with the compiler's search paths you can use a null 
form of Internal_Tests for your production software.

- Second way: Make the *internals* into a private child of the public 
main package:

package Test_Me is
    -- Just the public operations:
    procedure Public_Operation;
end Test_Me;


private package Test_Me.Internals is
    -- Declarations of all the "internals" that you
    -- want to test, plus all of the operations that you
    -- want to make public.
    procedure Internal_Operation;
    procedure Public_Operation;
end Test_Me.Internals;


with Test_Me.Internals;
package body Test_Me is
    -- Route (by renamings or calls) all public operations
    -- to their implementations in Test_Me.Internals:
    procedure Public_Operation
    renames Internals.Public_Operation;
end Test_Me;


Then write the test procedure as a child:

procedure Test_Me.Internals.Test is
begin
    Internal_Operation;
end Test_Me.Internals.Test;


-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Testing a package's internal details.
  2010-03-05  6:41 ` Niklas Holsti
@ 2010-03-05 11:25   ` Peter C. Chapin
  0 siblings, 0 replies; 4+ messages in thread
From: Peter C. Chapin @ 2010-03-05 11:25 UTC (permalink / raw)


Niklas Holsti wrote:

> I've seen two ways to do this...

Thanks for your note... very interesting. I'll reflect on your suggestions and
see what I come up with.

Peter




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Testing a package's internal details.
  2010-03-05  0:57 Testing a package's internal details Peter C. Chapin
  2010-03-05  6:41 ` Niklas Holsti
@ 2010-03-05 11:31 ` Stephen Leake
  1 sibling, 0 replies; 4+ messages in thread
From: Stephen Leake @ 2010-03-05 11:31 UTC (permalink / raw)


"Peter C. Chapin" <pcc482719@gmail.com> writes:

> A situation has come up for me and I'm wondering what the "best" way is to
> handle it. Here are the particulars...
>
> I have a package that models a single abstract object. The specification
> declares the operations that are allowed on the object. I would like to write
> some test procedures that can be used to exercise my implementation. Using a
> test program that exists outside the package, I can treat the package like a
> black box and call the public interface to the package during my tests. That
> is fine.

Ok so far.

> However, I'd also like to write some test procedures that independently
> exercise certain internal facilities without being constrained by the public
> interface. Those procedures are not really part of the abstraction I'm trying
> to present and I don't really want normal client code to call them. I do want
> the test program to call them, of course.
>
> Is there a "best practice" in this area that I should be following? At first I
> thought I might be able to make my test procedures part of a child package
> but that doesn't work because a child package has no access to the internal
> part of the parent's body (true?). 

Right.

> I suppose I could declare the test procedures in the private part of
> the parent's specification and then provide a child with a public
> procedure that just calls the parent's private test procedure.

Better to make the actual operations visible in the private part:

package Test_Me is
  -- ...
private
  procedure Private_Op_1;
  function Private_Op_2 return string;
end Test_Me;

package Test_Me.Tester is
  procedure Test_Private_Op_1;
  procedure Test_Private_op_2;
end Test_Me.Tester;

Or, if the private ops are fairly complicated, and use complicated
types, move them to a separate private package:

package Test_Me is

end Test_Me;

private
package Test_Me.internals is
end test_me.internals;

with test_me.internals;
package body test_me is

    -- stuff that uses test_me.internals

end test_me;

private
package test_me.internals.tester is

...
end test_me.internals.tester;

To work with a framework like AUnit, you sometimes have to declare a
public access package:

package Test_Me.internals_aux is

    procedure private_op_1; 

end test_Me.internals_aux;

Test_Me.internals_Aux.private_op_1 calls the real
test_me.internals.private_op_1.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-03-05 11:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-05  0:57 Testing a package's internal details Peter C. Chapin
2010-03-05  6:41 ` Niklas Holsti
2010-03-05 11:25   ` Peter C. Chapin
2010-03-05 11:31 ` Stephen Leake

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox