0
# Matchers and Types
1
2
Pattern matching and parameter conversion system for extracting and transforming data from step text into Python objects. Supports multiple matching strategies and custom type registration.
3
4
## Capabilities
5
6
### Type Registration
7
8
Register custom step parameter types for converting matched text into specific Python objects. This enables automatic type conversion in step parameters.
9
10
```python { .api }
11
def register_type(name: str, func):
12
"""
13
Register a custom type converter for step parameters.
14
15
Parameters:
16
- name: str, name to use in step patterns (e.g., "color", "number")
17
- func: callable, function that converts matched string to desired type
18
19
Returns:
20
None
21
"""
22
```
23
24
Usage example:
25
```python
26
# Define type converter
27
def parse_color(text):
28
color_map = {
29
'red': '#FF0000',
30
'green': '#00FF00',
31
'blue': '#0000FF'
32
}
33
return color_map.get(text.lower(), text)
34
35
# Register the type
36
register_type('color', parse_color)
37
38
# Use in step definition
39
@given('the background is {color:color}')
40
def step_impl(context, color):
41
# color parameter is automatically converted
42
context.background_color = color # e.g., '#FF0000' for 'red'
43
```
44
45
### Step Matcher Selection
46
47
Set the step matcher to use for pattern matching in the current module. Different matchers provide different pattern syntax options.
48
49
```python { .api }
50
def use_step_matcher(name: str):
51
"""
52
Set the step matcher to use for current module.
53
54
Parameters:
55
- name: str, matcher name ("parse", "cfparse", "re")
56
57
Returns:
58
None
59
"""
60
```
61
62
Usage example:
63
```python
64
# Use parse matcher (default)
65
use_step_matcher("parse")
66
67
@given('I have {count:d} items')
68
def step_impl(context, count):
69
pass
70
71
# Use regular expression matcher
72
use_step_matcher("re")
73
74
@given(r'I have (\d+) items')
75
def step_impl(context, count):
76
count = int(count) # Manual conversion needed
77
```
78
79
## Step Matchers
80
81
Behave supports multiple step matching strategies:
82
83
### Parse Matcher
84
85
Default matcher using parse library syntax for simple parameter extraction with type conversion.
86
87
```python { .api }
88
class ParseMatcher:
89
"""
90
Parse-based step matcher using parse library for parameter extraction.
91
92
Methods:
93
- check_match(pattern, step_text): Check if pattern matches step text
94
- match(pattern, step_text): Extract parameters from matched step text
95
"""
96
```
97
98
Parse patterns support:
99
- `{name}` - matches any text
100
- `{name:d}` - matches integers
101
- `{name:f}` - matches floats
102
- `{name:w}` - matches words (no whitespace)
103
- `{name:S}` - matches non-whitespace
104
- Custom types via `register_type()`
105
106
### Case-insensitive Parse Matcher
107
108
Parse matcher that ignores case differences in step text.
109
110
```python { .api }
111
class CFParseMatcher:
112
"""
113
Case-insensitive parse matcher.
114
115
Methods:
116
- check_match(pattern, step_text): Check if pattern matches (case-insensitive)
117
- match(pattern, step_text): Extract parameters (case-insensitive)
118
"""
119
```
120
121
### Regular Expression Matcher
122
123
Traditional regex-based matcher for complex patterns requiring full regular expression support.
124
125
```python { .api }
126
class RegexMatcher:
127
"""
128
Regular expression-based step matcher.
129
130
Methods:
131
- check_match(pattern, step_text): Check if regex pattern matches
132
- match(pattern, step_text): Extract groups from regex match
133
"""
134
```
135
136
### Cucumber Expression Matcher
137
138
Cucumber-style expression matcher for compatibility with Cucumber frameworks.
139
140
```python { .api }
141
class CucumberExpressionMatcher:
142
"""
143
Cucumber-style expression matcher.
144
145
Methods:
146
- check_match(pattern, step_text): Check if Cucumber expression matches
147
- match(pattern, step_text): Extract parameters from Cucumber expression
148
"""
149
```
150
151
## Type Registry
152
153
Central registry for managing custom parameter types and their conversion functions.
154
155
```python { .api }
156
class TypeRegistry:
157
"""
158
Registry for managing custom parameter type converters.
159
160
Methods:
161
- register_type(name, func): Register a type converter function
162
- convert(name, value): Convert value using registered type converter
163
- get_type(name): Get registered type converter by name
164
- clear(): Remove all registered type converters
165
"""
166
```
167
168
## Built-in Types
169
170
Behave includes several built-in parameter types:
171
172
### Numeric Types
173
```python
174
# Integer type
175
@given('I have {count:d} items')
176
def step_impl(context, count):
177
# count is automatically converted to int
178
assert isinstance(count, int)
179
180
# Float type
181
@given('the price is {amount:f} dollars')
182
def step_impl(context, amount):
183
# amount is automatically converted to float
184
assert isinstance(amount, float)
185
```
186
187
### String Types
188
```python
189
# Word type (no whitespace)
190
@given('the status is {status:w}')
191
def step_impl(context, status):
192
# status contains no whitespace
193
assert ' ' not in status
194
195
# Non-whitespace type
196
@given('the code is {code:S}')
197
def step_impl(context, code):
198
# code contains no whitespace characters
199
assert not any(c.isspace() for c in code)
200
```
201
202
## Custom Type Examples
203
204
### Boolean Type
205
```python
206
def parse_bool(text):
207
text = text.lower()
208
if text in ('true', 'yes', '1', 'on', 'enabled'):
209
return True
210
elif text in ('false', 'no', '0', 'off', 'disabled'):
211
return False
212
else:
213
raise ValueError(f"Cannot convert '{text}' to boolean")
214
215
register_type('bool', parse_bool)
216
217
@given('the feature is {enabled:bool}')
218
def step_impl(context, enabled):
219
context.feature_enabled = enabled
220
```
221
222
### Date Type
223
```python
224
from datetime import datetime
225
226
def parse_date(text):
227
try:
228
return datetime.strptime(text, '%Y-%m-%d')
229
except ValueError:
230
try:
231
return datetime.strptime(text, '%m/%d/%Y')
232
except ValueError:
233
raise ValueError(f"Cannot parse date: {text}")
234
235
register_type('date', parse_date)
236
237
@given('the event date is {date:date}')
238
def step_impl(context, date):
239
context.event_date = date
240
```
241
242
### Enum Type
243
```python
244
from enum import Enum
245
246
class Priority(Enum):
247
LOW = 'low'
248
MEDIUM = 'medium'
249
HIGH = 'high'
250
251
def parse_priority(text):
252
try:
253
return Priority(text.lower())
254
except ValueError:
255
raise ValueError(f"Invalid priority: {text}")
256
257
register_type('priority', parse_priority)
258
259
@given('the task priority is {priority:priority}')
260
def step_impl(context, priority):
261
context.task_priority = priority
262
```
263
264
### List Type
265
```python
266
def parse_list(text):
267
# Parse comma-separated values
268
return [item.strip() for item in text.split(',')]
269
270
register_type('list', parse_list)
271
272
@given('the tags are {tags:list}')
273
def step_impl(context, tags):
274
context.tags = tags # ['tag1', 'tag2', 'tag3']
275
```
276
277
## Advanced Pattern Matching
278
279
### Optional Parameters
280
```python
281
# Using parse syntax with optional parts
282
@given('I {action} {count:d} item(s)')
283
def step_impl(context, action, count):
284
# Matches both "I add 1 item" and "I add 5 items"
285
pass
286
```
287
288
### Alternative Patterns
289
```python
290
# Multiple patterns for same step
291
@given('I am logged in')
292
@given('I am authenticated')
293
def step_impl(context):
294
context.authenticated = True
295
```
296
297
### Complex Regex Patterns
298
```python
299
use_step_matcher("re")
300
301
@given(r'I have (\d+) (\w+)(?:s)? in my (\w+)')
302
def step_impl(context, count, item_type, container):
303
count = int(count)
304
# Handles pluralization automatically
305
pass
306
```