使用GNAT测试时如何为功能添加第二个测试?

时间:2018-09-13 09:04:18

标签: unit-testing ada gnat aunit

documentation for Gnat测试展示了如何生成线束和骨架单元测试。它为目标项目中的每个公共功能创建一个单元测试,但是如果添加另一个单元测试,则在重新生成线束和骨架单元测试时会被覆盖。

在gnattest提供的simple example项目中,如何添加另一个测试?我尝试过:

(1)向已经存在的测试功能添加另一条Assert行。这行得通,但不是好习惯;第一个失败的测试将阻止其他测试运行。

(2)将函数定义添加到obj / gnattest / harness / gnattest.xml,然后regenerating the tests无效; xml文件在用于创建测试存根之前已重新生成。

(3)通过以下更改将定义手动添加到测试/和控制/中,这些更改会因重新生成测试而变得混乱。

将此添加到obj / gnattest / tests / simple-test_data-tests.ads:

   procedure Test_Inc2_4f8b9f (Gnattest_T : in out Test);

将此添加到obj / gnattest / tests / simple-test_data-tests.adb:

--  begin read only
   procedure Test_Inc2 (Gnattest_T : in out Test);
   procedure Test_Inc2_4f8b9f (Gnattest_T : in out Test) renames Test_Inc2;
--  id:2.2/4f8b9f38b0ce8c74/Inc/1/0/
   procedure Test_Inc2 (Gnattest_T : in out Test) is
   --  simple.ads:7:4:Inc
--  end read only
   begin
     Assert (Inc(2) = 2, "this test should fail");
--  begin read only
   end Test_Inc2;
--  end read only

在obj / gnattest / harness / simple-test_data-tests-suite.adb中将声明添加到第16行,并将create和add_test添加到Suite函数:

   Case_1_1_Test_Inc2_4f8b9f : aliased Runner_1.Test_Case;

  Runner_1.Create
    (Case_1_1_Test_Inc2_4f8b9f,
     "simple2.ads:7:4:",
     Test_Inc2_4f8b9f'Access);
  Result.Add_Test (Case_1_1_Test_Inc2_4f8b9f'Access);

要重新编译,请不要使用Makefile,因为这会破坏更改。而是运行

gprbuild -Pobj/gnattest/harness/test_driver.gpr
./obj/gnattest/harness/test_runner.exe`.

必须有更好的方法。

1 个答案:

答案 0 :(得分:1)

如果您不介意修改测试主题(并且在此过程中失去了一点可移植性……),则有一个特定于GNAT的实用术语或方面(Ada 2012)

我将首先显示编译指示的语法,其余示例将使用方面语法:

function Foo(Bar : in Integer) return Integer;
pragma Test_Case("Test 1", Robustness);

相同的方面语法示例:

function Foo(Bar : in Integer) return Integer
   with Test_Case => ("Test 1", Robustness);

或者,如果您喜欢命名关联:

function Foo(Bar : in Integer) return Integer
   with Test_Case => (Name => "Test 1", Mode => Robustness);

除非您指定Mode => Nominal(请参见下文)或两个可选参数Requires和{{ 1}}:

Ensures

function Foo(Bar : in Integer) return Integer with Test_Case => (Name => "Test 1", Mode => Robustness, Requires => Bar < 10, Ensures => Foo'Result > 15); 充当特定于测试案例的前提条件, Requires充当特定于测试用例的后置条件, 它将由生成的包装器代码检查。 如果您在测试对象上已有EnsuresPre条件,则如果指定Post,则生成的代码也可以检查这些条件。 (使用Mode => Nominal时,它们将被忽略)。

Mode => Robustness

当然,您可以添加多个function Foo(Bar : in Integer) return Integer with Pre => Bar > 5, Post => Foo'Result < 10, Test_Case => (Name => "Test 1", Mode => Nominal, Requires => Bar < 10, Ensures => Foo'Result > 15);

Test_Case