打破测试功能的 Ada 隐私
Breaking Ada privacy for Test functions
假设我有两个包裹:
with Ada.Streams; use Ada.Streams;
package P is
type SEA is new Stream_Element_Array (1..4);
function foo (Input : in SEA) return Natural;
private
type PRecord is record
Bar : Natural := 0;
end record;
function To_PRecord is new Ada.Unchecked_Conversion
(Source => SEA,
Target => PRecord);
end P;
------
package body P is
function foo (Input : in SEA) return Natural
is
Tmp : constant PRecord := To_PRecord (Input);
begin
return Tmp.Bar;
end foo;
end P;
和
-- Say SEA was defined in a third package and is accessible
package Q is
function foo (Input : SEA) return Natural;
end P;
-----
with P;
package body Q is
function foo (Input : SEA) return Natural
is
begin
return P.foo(Input);
end foo;
end Q;
包 P 很容易测试:
with AUnit.Assertions; use AUnit.Assertions;
package body P.Tests is
function To_SEA is new Ada.Unchecked_Conversion
(Source => PRecord,
Target => SEA);
procedure Test_Foo
is
Input : PRecord := (Bar => 42);
begin
Assert (foo(To_SEA (Input)) = 42, "foo failed miserably");
end Test_Foo;
end P.Tests;
但是我该如何测试 Q? PRecord
无法访问。因此,我看不出 Q 如何在不改变我正在测试的代码的情况下进行测试。在 C++ 中,我会将包 Q.Tests
定义为 P
的 friend
并获得访问权限。
我想我可以在 P
和 Q.Tests
可以使用的包中定义 PRecord
但是有没有不需要更改 P 或 Q 的解决方案(因为我真的不喜欢为了测试而需要更改生产代码。
子包 P.Spy
可以看到整个 P
的规范; Q.Tests
可以调用它来进行验证检查。
根据 Simon Wright 的回答,可以定义 P.Spy
包如下:
package P.Spy is
function Create (Bar : in Natural) return SEA;
private
function To_SEA is new Ada.Unchecked_Conversion (Source => PRecord,Target => SEA);
end P.Spy;
---
package body P.Spy is
function Create (Bar : in Natural) return SEA
is
Result : PRecord;
begin
Result.Bar := Bar;
return To_SEA (Result);
end Create;
end P.Spy;
允许 Q.Tests
测试其 public 接口的能力。
假设我有两个包裹:
with Ada.Streams; use Ada.Streams;
package P is
type SEA is new Stream_Element_Array (1..4);
function foo (Input : in SEA) return Natural;
private
type PRecord is record
Bar : Natural := 0;
end record;
function To_PRecord is new Ada.Unchecked_Conversion
(Source => SEA,
Target => PRecord);
end P;
------
package body P is
function foo (Input : in SEA) return Natural
is
Tmp : constant PRecord := To_PRecord (Input);
begin
return Tmp.Bar;
end foo;
end P;
和
-- Say SEA was defined in a third package and is accessible
package Q is
function foo (Input : SEA) return Natural;
end P;
-----
with P;
package body Q is
function foo (Input : SEA) return Natural
is
begin
return P.foo(Input);
end foo;
end Q;
包 P 很容易测试:
with AUnit.Assertions; use AUnit.Assertions;
package body P.Tests is
function To_SEA is new Ada.Unchecked_Conversion
(Source => PRecord,
Target => SEA);
procedure Test_Foo
is
Input : PRecord := (Bar => 42);
begin
Assert (foo(To_SEA (Input)) = 42, "foo failed miserably");
end Test_Foo;
end P.Tests;
但是我该如何测试 Q? PRecord
无法访问。因此,我看不出 Q 如何在不改变我正在测试的代码的情况下进行测试。在 C++ 中,我会将包 Q.Tests
定义为 P
的 friend
并获得访问权限。
我想我可以在 P
和 Q.Tests
可以使用的包中定义 PRecord
但是有没有不需要更改 P 或 Q 的解决方案(因为我真的不喜欢为了测试而需要更改生产代码。
子包 P.Spy
可以看到整个 P
的规范; Q.Tests
可以调用它来进行验证检查。
根据 Simon Wright 的回答,可以定义 P.Spy
包如下:
package P.Spy is
function Create (Bar : in Natural) return SEA;
private
function To_SEA is new Ada.Unchecked_Conversion (Source => PRecord,Target => SEA);
end P.Spy;
---
package body P.Spy is
function Create (Bar : in Natural) return SEA
is
Result : PRecord;
begin
Result.Bar := Bar;
return To_SEA (Result);
end Create;
end P.Spy;
允许 Q.Tests
测试其 public 接口的能力。