Add initial support for predefined regexps.

These are hard-coded for now.
They also will not all work properly, since they need support for
non-grouping parenthesis in g-regpat.ads
This commit is contained in:
Emmanuel Briot 2014-06-06 12:59:58 +02:00
parent dfc490af5a
commit c2a6d39687
3 changed files with 111 additions and 21 deletions

View File

@ -169,6 +169,11 @@ It is recommended that regular expressions always be surrounded with '^' and
'$', to indicate they should match the whole step definition, and not just part
of it.
.. _using_tables_in_step_definitions:
Using tables in step definitions
--------------------------------
Some steps include extra information, like a table or a multi-line string.
This information is not part of the regular expression, although the
subprogram should have one or more parameters for it. For instance::
@ -222,6 +227,38 @@ Many more variants of `Assert` exist, which are able to compare a lot of
the usual Ada types, as well as more advanced types like lists of strings, or
the tables that are used in the feature files to provide data to steps.
Automatic type conversion
=========================
By default, all the parenthesis group in your regular expressions are
associated with `String` parameters in the subprogram that implements the
step.
However, GNATbdd also accepts other types for parameters, and will
automatically convert the string to them. The types are matched with string
comparison, so they must be defined exactly as how they appear in the following
table (casing not withstanding), even if you are using use clauses in your
packages.
+-------------------+-----------------------------------------------------+
| Type | Description |
+===================+=====================================================+
| String | The default parameter type |
+-------------------+-----------------------------------------------------+
| Integer | Typically associated with (\d+) in the regexp |
| Natural | |
+-------------------+-----------------------------------------------------+
| Ada.Calendar.Time | Date (including optional time and timezone) |
| | "2014-01-01 13:00:00+01:00" |
| | "Thu, 19 Dec 2014 13:59:12" |
| | "19/12/2014" |
| | "12/19/2014" |
+-------------------+-----------------------------------------------------+
| BDD.Tables.Table | See :ref:`using_tables_in_step_definitions` |
+-------------------+-----------------------------------------------------+
| other types | GNATbdd will generate a type'Image call |
+-------------------+-----------------------------------------------------+
Predefined Regular Expressions
==============================
@ -229,25 +266,28 @@ Predefined Regular Expressions
To simplify the writting of your steps, GNATbdd provides a number of predefined
regular expressions that can be used in your own regular expressions. These
expressions have a name, that can be used in your regexps by using a leading
colon, as in::
percent sign, as in::
-- @then "^I should get :natural results";
-- @then "^I should get %natural results";
procedure My_Step (Expected : Integer);
The predefined regexps are automatically included in a parenthesis group,
so you should not add parenthesis yourself.
Here is the full list of predefined regular expressions:
+---------+----------------------------+-------------------+
| name | examples | Ada type |
+=========+============================+===================+
| integer | -1; 0; 234 | Integer |
+---------+----------------------------+-------------------+
| float | -1.0E+10; 002E-10 | Float |
+---------+----------------------------+-------------------+
| natural | 2; 56 | Natural |
+---------+----------------------------+-------------------+
| date | Feb 04, 2014; 2014-02-04 | Ada.Calendar.Time |
+---------+----------------------------+-------------------+
+---------+----------------------------+-----------------------------+
| name | examples | Ada type |
+=========+============================+=============================+
| integer | -1; 0; 234 | String or Integer |
+---------+----------------------------+-----------------------------+
| float | -1.0E+10; 002E-10 | String or Float |
+---------+----------------------------+-----------------------------+
| natural | 2; 56 | String or Natural |
+---------+----------------------------+-----------------------------+
| date | Feb 04, 2014; 2014-02-04 | String or Ada.Calendar.Time |
+---------+----------------------------+-----------------------------+
Predefined steps

View File

@ -6,7 +6,7 @@ package MySteps1 is
procedure When_I_Enter (Value : String)
with Pre => Value /= "";
-- @then ^I should read (\d+)$
-- @then ^I should read %integer$
procedure Then_I_Should_Read (Result : Integer);
-- @then ^the stack should contain$

View File

@ -27,6 +27,7 @@ with Ada.Unchecked_Deallocation;
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Regpat; use GNAT.Regpat;
with GNAT.Strings; use GNAT.Strings;
with GNATCOLL.Templates; use GNATCOLL.Templates;
with GNATCOLL.Traces; use GNATCOLL.Traces;
with GNATCOLL.Utils; use GNATCOLL.Utils;
@ -47,6 +48,31 @@ package body Gnatbdd.Codegen is
Cst_Comment_Re : constant Pattern_Matcher :=
Compile ("--\s*@(given|then|when)\s+");
Predefined_Regexps : constant Substitution_Array :=
(1 => (new String'("integer"),
new String'("([-+]?\d+)")),
2 => (new String'("float"),
-- ??? This introduces an extra pair of parenthesis, should add
-- support for non-grouping parenthesis in g-regpat
new String'("([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?)")),
3 => (new String'("natural"),
new String'("(\+?\d+)")),
4 => (new String'("date"),
new String'(
"((?:" -- date part
& "\d{4}/\d{2}/\d{2}" -- 2014/01/02
& "|"
& "\d{2}/\d{2}/\d{4}" -- 01/02/2014
& "|"
& "\d{4}-\d{2}-\d{2}" -- 2014-01-02
& ")" -- end of date part
& "(?:\s+" -- optional time part
& "\d{2}:\d{2}:\d{2}" -- hh:mm:ss
& "(?:\s*[+-]\d{2})" -- optional time zone within time
& "))"
))
);
type Generated_Data is record
Matchers : Unbounded_String;
-- Code extract that, for a given step, checks all known step definition
@ -107,6 +133,9 @@ package body Gnatbdd.Codegen is
type Param_List_Access is access all Param_List;
procedure Free (Self : in out Param_List_Access);
function Substitute_Predefined_Regexps (Regexp : String) return String;
-- Replace occurrences of predefined regexps
----------
-- Free --
----------
@ -189,14 +218,33 @@ package body Gnatbdd.Codegen is
--------------------
function String_To_Type (Typ, Value : String) return String is
T : constant String := To_Lower (Typ);
begin
if To_Lower (Typ) = "string" then
if T = "string" then
return Value;
elsif T = "ada.calendar.time" then
return "GNATCOLL.Utils.Time_Value (" & Value & ")";
else
return Typ & "'Value (" & Value & ")";
end if;
end String_To_Type;
-----------------------------------
-- Substitute_Predefined_Regexps --
-----------------------------------
function Substitute_Predefined_Regexps (Regexp : String) return String is
begin
return GNATCOLL.Templates.Substitute
(Str => Regexp,
Substrings => Predefined_Regexps,
Delimiter => '%',
Recursive => True,
Errors => Keep_As_Is);
end Substitute_Predefined_Regexps;
--------------------------
-- Parse_Subprogram_Def --
--------------------------
@ -456,7 +504,8 @@ package body Gnatbdd.Codegen is
Parse_Subprogram_Def
(Contents.all,
Package_Name => Contents (Pack_Start .. Pack_End),
Regexp => Contents (Start .. Last - 1),
Regexp => Substitute_Predefined_Regexps
(Contents (Start .. Last - 1)),
Found => Found,
Data => Data,
Pos => Pos);
@ -526,11 +575,12 @@ package body Gnatbdd.Codegen is
Create_From_Dir
(Object_Dir, +Driver & ".adb").Display_Full_Name);
Put_Line (F, "-- Automatically generated");
Put_Line (F, "with BDD; use BDD;");
Put_Line (F, "with BDD.Main; use BDD.Main;");
Put_Line (F, "with BDD.Features; use BDD.Features;");
Put_Line (F, "with BDD.Runner; use BDD.Runner;");
Put_Line (F, "with GNAT.Regpat; use GNAT.Regpat;");
Put_Line (F, "with BDD; use BDD;");
Put_Line (F, "with BDD.Main; use BDD.Main;");
Put_Line (F, "with BDD.Features; use BDD.Features;");
Put_Line (F, "with BDD.Runner; use BDD.Runner;");
Put_Line (F, "with GNAT.Regpat; use GNAT.Regpat;");
Put_Line (F, "with GNATCOLL.Utils; use GNATCOLL.Utils;");
Put_Line (F, To_String (Data.Withs));
Put_Line (F, "procedure " & Driver & " is");
New_Line (F);