From: Tero Koskinen on
On Fri, 04 Jun 2010 05:17:51 -0400 Stephen Leake wrote:

> Dan <dan(a)irvine.com> writes:
>
> > On Jun 3, 5:08 am, Stephen Leake <stephen_le...(a)stephe-leake.org>
> > wrote:
> >> How does it compare to AUnit?

Here a little summary:
* The basic API is similar in Ahven and AUnit 1 (and 3).
* In Ahven, I have the public API stuffed into two packages:
Ahven and Ahven.Framework while AUnit spreads it API into
larger amount of packages.

* AUnit is Ada 2005 code only and I think it can be compiled
only with GNAT (not 100% sure since I haven't tried it with
other Ada 2005 compilers)
* Ahven is Ada 95 code, but can be compiled as Ada 2005 code also.
I have seen some effort to make Ahven build out of the box
with several Ada 95 or Ada 2005 compilers. So far, GNAT,
Janus/Ada, ObjectAda, and ICCAda have been tested.
(Unix and Windows environments)

I don't know about IBM/Rational Apex, GHS AdaMulti, or PowerAda,
but I suspect that they should be okay also.

* Both are free or open-source software.
AUnit is distributed under GPL and Ahven under ISC
license (similar to BSD).

* Both libraries support XML results, but AUnit uses CppUnit's
XML format while Ahven uses JUnit's format.
In addition, Ahven can output test results in
Test-Anything-Protocol (TAP) format, which is my favorite
at the moment.

* AUnit's documentation is probably better. So far I have
concentrated on the code.

> In AUnit, tests are 'registered' in a test_case:
>
> overriding procedure Register_Tests (T : in out Test_Case)
> is
> begin
> Register_Routine (T, Nominal'Access, "Nominal");

Same works for Ahven. Dan's example was just somewhat exotic, so
one couldn't figure it out from that.

procedure Initialize (T: in out Test_Case) is
procedure Register_Routine
(T : in out Ahven.Framework.Test_Case'Class;
Routine : Simple_Test_Routine_Access;
Name : String) renames Ahven.Framework.Add_Test_Routine;
begin
Register_Routine (T, Nominal'Access, "Nominal");
...;

The difference is in the test routine signature.

AUnit accepts only form
procedure Nominal (T : in out AUnit.Test_Cases.Test_Case'Class);

while Ahven accepts
procedure Nominal (T : in out Ahven.Framework.Test_Case'Class);
and
procedure Nominal;

> Then test_cases are added to suites:
>
> Add_Test (Suite, new Test_Hardware.Analog_In_Out_Wrappers.Test_Case);
> Add_Test (Suite, new Test_Hardware.Analog_In_Wrapper_Common.Test_Case);
> Add_Test (Suite, new Test_Hardware.Analog_Out_Wrapper_Common.Test_Case);
>
> This seems roughly equivalent to Ahven.

Yes.

> AUnit also has setup and teardown functions for initializing and finalizing
> each test and/or each Test_Case; those are very helpful.

Ahven supports setup and teardown procedures for each test.

For each Test_Case you need to rely on Initialize and Finalize
procedures provided by Ada.Finalization.Controlled.

package body Simple_Tests is
type Test_Access is access all Test;

procedure Initialize (T : in out Test) is
begin
Set_Name (T, "Simple Tests");

Ahven.Framework.Add_Test_Routine
(T, Test_Assertion'Access, "Test Assertion");
Ahven.Framework.Add_Test_Routine
(T, Test_With_Object'Access, "Test With Object");
Ahven.Framework.Add_Test_Routine
(T, Test_Error'Access, "Test Error (exception)");

end Initialize;

procedure Set_Up (T : in out Test) is
begin
Put_Line ("Simple_Tests.Set_Up");
T.Value := 1;
end Set_Up;

procedure Tear_Down (T : in out Test) is
begin
Put_Line ("Simple_Tests.Tear_Down");
T.Value := -1;
end Tear_Down;

procedure Test_Assertion is
begin
Put_Line ("Test_Assertion");
Ahven.Assert (False, "assert(false)");
end Test_Assertion;

procedure Test_Error is
begin
raise Constraint_Error;
end Test_Error;

procedure Hello (T : Test) is
begin
Ahven.Assert (T.Value = 1, "T.Value = 1");
end Hello;

procedure Test_With_Object (T : in out Ahven.Framework.Test_Case'Class) is
begin
Put_Line ("Test_With_Object");
Hello (Test (T));
end Test_With_Object;
end Simple_Tests;


There are probably also other differences, but
I don't want to spoil too much. ;)

> --
> -- Stephe


--
Tero Koskinen - http://iki.fi/tero.koskinen/
From: Dan on
On Jun 4, 2:17 am, Stephen Leake <stephen_le...(a)stephe-leake.org>
wrote:
> Dan <d...(a)irvine.com> writes:
> > On Jun 3, 5:08 am, Stephen Leake <stephen_le...(a)stephe-leake.org>
> > wrote:
> >> How does it compare to AUnit?
>
> > I am able to use Ahven in a table-driven manner, as shown below.
> > But I don't see a way to use AUnit similarly (replacing the Ahven-
> > specific code below the line of dashes).
>
> > ...
> > with p1, p2, p3;
> > with test_suite; use test_suite;
> > package p_suite is new test_suite.suites(
> >      suite_name => "p",
> >      suite_arr => (
> >         (p1'access, +"p1"),
> >         (p2'access, +"p3"),
> >         (p3'access, +"p3")));
>
> In AUnit, tests are 'registered' in a test_case:
>
>    overriding procedure Register_Tests (T : in out Test_Case)
>    is
>    begin
>         Register_Routine (T, Nominal'Access, "Nominal");
>         Register_Routine (T, Commands'Access, "Commands");
>         Register_Routine (T, Glitches'Access, "Glitches");
>         Register_Routine (T, Multi_Cycle'Access, "Multi_Cycle");
>   end Register_Tests;
>
> Then test_cases are added to suites:
>
>    Add_Test (Suite, new Test_Hardware.Analog_In_Out_Wrappers.Test_Case);
>    Add_Test (Suite, new Test_Hardware.Analog_In_Wrapper_Common.Test_Case);
>    Add_Test (Suite, new Test_Hardware.Analog_Out_Wrapper_Common.Test_Case);
>
> This seems roughly equivalent to Ahven.
>
> AUnit also has setup and teardown functions for initializing and finalizing
> each test and/or each Test_Case; those are very helpful.
>
> --
> -- Stephe

There is a significant difference in registering tests between Ahven
and Aunit, which Tero mentions, but I will expand on.

Ahven accepts parameterless procedures as test routines,
such as the p1,p2,p3,q1,q2,q3 in my example. AUnit, in contrast,
requires test routines to have a parameter of type
AUnit.Test_Cases.Test_Case'Class. I have thousands of procedures that
I would like to test using a test driver, but unfortunately not a
single one of those comes in the form AUnit requires.

If you start with an array of parameterless test procedures, AUnit
requires that you traverse the array, creating a new test procedure
(containing the required parameter) for each parameterless test
procedure in the array. Then you can register the newly created test
procedures.

The problem is that Ada doesn't have a good way for one procedure to
create other procedures, that can then be registered (using 'access).
I tried using generics to instantiate the new test procedures, but ran
into accessiblity-level problems. I also tried using an allocator of
a protected type that contains a procedure, but that results in a
protected procedure, and AUnit only knows how to register normal
(unprotected) procedures.

I presume that it may be possible to modify AUnit to support
registering parameterless test procedures (or even better, an array of
them), which would be convenient for my purposes. It would also be
possible to write some sort of offline test-generator that creates the
kind of test procedures that AUnit expects.
From: Stephen Leake on
Dan <dan(a)irvine.com> writes:

> Ahven accepts parameterless procedures as test routines,
> such as the p1,p2,p3,q1,q2,q3 in my example. AUnit, in contrast,
> requires test routines to have a parameter of type
> AUnit.Test_Cases.Test_Case'Class. I have thousands of procedures that
> I would like to test using a test driver, but unfortunately not a
> single one of those comes in the form AUnit requires.

Ah. Adapting an existing test suite to use the framework is an issue.

You could write one AUnit test that calls all the thousands of tests,
but that would be silly.

You could probably write a tool to convert those tests to match AUnit,
but that would still be a lot of work.

> The problem is that Ada doesn't have a good way for one procedure to
> create other procedures, that can then be registered (using 'access).
> I tried using generics to instantiate the new test procedures, but ran
> into accessiblity-level problems. I also tried using an allocator of
> a protected type that contains a procedure, but that results in a
> protected procedure, and AUnit only knows how to register normal
> (unprotected) procedures.

You need to write new source code. Real software writes itself :) (a new
slogan I just made up :).

> I presume that it may be possible to modify AUnit to support
> registering parameterless test procedures (or even better, an array of
> them), which would be convenient for my purposes.

Not easy; the tests are called by the standard Ada dispatching call methods.

> It would also be possible to write some sort of offline test-generator
> that creates the kind of test procedures that AUnit expects.

Yes.

--
-- Stephe
From: Simon Wright on
Tero Koskinen <tero.koskinen(a)iki.fi> writes:

> * AUnit is Ada 2005 code only and I think it can be compiled
> only with GNAT (not 100% sure since I haven't tried it with
> other Ada 2005 compilers)

The 2005-ness occurs because AUnit uses a private copy of
Ada.Containers.Lists with some 05 constructs removed so that it can be
compiled with "an" Ada 95 compiler.

Unfortunately, what they mean is "with an Ada 95 compiler that
recognises pragma Ada_2005 to mean that some Ada 2005 constructs are
permitted even when compiling in Ada 95 mode".

This doesn't include older GNATs, and certainly won't include compilers
from other vendors.

These patches update the current SVN source of AUnit to work with older
GNATs. Ask me if you need a copy and the news system has mangled them or
I've failed to drive Emacs correctly ...

From: Ludovic Brenta on
Simon Wright <simon(a)pushface.org> writes:
> Tero Koskinen <tero.koskinen(a)iki.fi> writes:
>
>> * AUnit is Ada 2005 code only and I think it can be compiled
>> only with GNAT (not 100% sure since I haven't tried it with
>> other Ada 2005 compilers)
>
> The 2005-ness occurs because AUnit uses a private copy of
> Ada.Containers.Lists with some 05 constructs removed so that it can be
> compiled with "an" Ada 95 compiler.
>
> Unfortunately, what they mean is "with an Ada 95 compiler that
> recognises pragma Ada_2005 to mean that some Ada 2005 constructs are
> permitted even when compiling in Ada 95 mode".
>
> This doesn't include older GNATs, and certainly won't include compilers
> from other vendors.
>
> These patches update the current SVN source of AUnit to work with older
> GNATs. Ask me if you need a copy and the news system has mangled them or
> I've failed to drive Emacs correctly ...

Stephe, how about applying this patch to Debian's version of AUnit?

--
Ludovic Brenta.