Testing And Benchmarking in Ada

Here’s the translation of the Go testing and benchmarking example to Ada:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Assertions; use Ada.Assertions;

procedure Testing_And_Benchmarking is

   -- We'll be testing this simple implementation of an
   -- integer minimum. Typically, the code we're testing
   -- would be in a separate package file named something like
   -- "Int_Utils.ads" and "Int_Utils.adb".

   function Int_Min (A, B : Integer) return Integer is
   begin
      if A < B then
         return A;
      end if;
      return B;
   end Int_Min;

   -- A test is created by writing a procedure.

   procedure Test_Int_Min_Basic is
      Ans : Integer;
   begin
      Ans := Int_Min (2, -2);
      if Ans /= -2 then
         -- Assert.Fail will report test failures and raise an exception.
         Assert (False, "Int_Min(2, -2) = " & Integer'Image(Ans) & "; want -2");
      end if;
   end Test_Int_Min_Basic;

   -- Writing tests can be repetitive, so it's common to use a
   -- table-driven style, where test inputs and expected outputs
   -- are listed in an array and a single loop walks over them
   -- and performs the test logic.

   procedure Test_Int_Min_Table_Driven is
      type Test_Case is record
         A, B : Integer;
         Want : Integer;
      end record;

      Test_Cases : constant array (Positive range <>) of Test_Case := (
         (0, 1, 0),
         (1, 0, 0),
         (2, -2, -2),
         (0, -1, -1),
         (-1, 0, -1)
      );
   begin
      for I in Test_Cases'Range loop
         declare
            TC : Test_Case renames Test_Cases (I);
            Ans : Integer;
         begin
            Ans := Int_Min (TC.A, TC.B);
            if Ans /= TC.Want then
               Assert (False, "got " & Integer'Image(Ans) & ", want " & Integer'Image(TC.Want));
            end if;
         end;
      end loop;
   end Test_Int_Min_Table_Driven;

   -- Benchmark tests in Ada are typically done using external
   -- tools or libraries, as Ada doesn't have built-in benchmarking
   -- facilities like Go. Here's a simple timing example:

   procedure Benchmark_Int_Min is
      Start_Time, End_Time : Time;
      Iterations : constant := 1_000_000;
   begin
      Start_Time := Clock;
      for I in 1 .. Iterations loop
         Int_Min (1, 2);
      end loop;
      End_Time := Clock;

      Put_Line ("Time taken for " & Integer'Image(Iterations) & " iterations: " &
                Duration'Image(End_Time - Start_Time) & " seconds");
   end Benchmark_Int_Min;

begin
   Put_Line ("Running tests...");
   Test_Int_Min_Basic;
   Test_Int_Min_Table_Driven;
   Put_Line ("All tests passed.");

   Put_Line ("Running benchmark...");
   Benchmark_Int_Min;
end Testing_And_Benchmarking;

To run this Ada program, you would typically compile it and then run the resulting executable. The exact commands may vary depending on your Ada compiler, but with GNAT it might look like this:

$ gnatmake testing_and_benchmarking.adb
$ ./testing_and_benchmarking
Running tests...
All tests passed.
Running benchmark...
Time taken for 1000000 iterations: 0.016000000 seconds

Note that Ada doesn’t have a built-in testing framework like Go’s testing package. In practice, Ada projects often use external testing frameworks like AUnit. The benchmarking facility shown here is a simple timing mechanism and doesn’t provide the same level of detail as Go’s benchmarking tools. For more sophisticated benchmarking in Ada, you might use external profiling tools or create more detailed timing mechanisms.

Ada’s strong typing and compiler checks can catch many errors at compile-time, reducing the need for certain types of runtime tests. However, unit testing is still an important practice in Ada development for ensuring correct behavior of complex logic.