CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-behave

Behavior-driven development testing framework for Python using Gherkin syntax

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

matchers-types.mddocs/

Matchers and Types

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.

Capabilities

Type Registration

Register custom step parameter types for converting matched text into specific Python objects. This enables automatic type conversion in step parameters.

def register_type(name: str, func):
    """
    Register a custom type converter for step parameters.
    
    Parameters:
    - name: str, name to use in step patterns (e.g., "color", "number")
    - func: callable, function that converts matched string to desired type
    
    Returns:
    None
    """

Usage example:

# Define type converter
def parse_color(text):
    color_map = {
        'red': '#FF0000',
        'green': '#00FF00', 
        'blue': '#0000FF'
    }
    return color_map.get(text.lower(), text)

# Register the type
register_type('color', parse_color)

# Use in step definition
@given('the background is {color:color}')
def step_impl(context, color):
    # color parameter is automatically converted
    context.background_color = color  # e.g., '#FF0000' for 'red'

Step Matcher Selection

Set the step matcher to use for pattern matching in the current module. Different matchers provide different pattern syntax options.

def use_step_matcher(name: str):
    """
    Set the step matcher to use for current module.
    
    Parameters:
    - name: str, matcher name ("parse", "cfparse", "re")
    
    Returns:
    None
    """

Usage example:

# Use parse matcher (default)
use_step_matcher("parse")

@given('I have {count:d} items')
def step_impl(context, count):
    pass

# Use regular expression matcher  
use_step_matcher("re")

@given(r'I have (\d+) items')
def step_impl(context, count):
    count = int(count)  # Manual conversion needed

Step Matchers

Behave supports multiple step matching strategies:

Parse Matcher

Default matcher using parse library syntax for simple parameter extraction with type conversion.

class ParseMatcher:
    """
    Parse-based step matcher using parse library for parameter extraction.
    
    Methods:
    - check_match(pattern, step_text): Check if pattern matches step text
    - match(pattern, step_text): Extract parameters from matched step text
    """

Parse patterns support:

  • {name} - matches any text
  • {name:d} - matches integers
  • {name:f} - matches floats
  • {name:w} - matches words (no whitespace)
  • {name:S} - matches non-whitespace
  • Custom types via register_type()

Case-insensitive Parse Matcher

Parse matcher that ignores case differences in step text.

class CFParseMatcher:
    """
    Case-insensitive parse matcher.
    
    Methods:
    - check_match(pattern, step_text): Check if pattern matches (case-insensitive)
    - match(pattern, step_text): Extract parameters (case-insensitive)
    """

Regular Expression Matcher

Traditional regex-based matcher for complex patterns requiring full regular expression support.

class RegexMatcher:
    """
    Regular expression-based step matcher.
    
    Methods:
    - check_match(pattern, step_text): Check if regex pattern matches
    - match(pattern, step_text): Extract groups from regex match
    """

Cucumber Expression Matcher

Cucumber-style expression matcher for compatibility with Cucumber frameworks.

class CucumberExpressionMatcher:
    """
    Cucumber-style expression matcher.
    
    Methods:
    - check_match(pattern, step_text): Check if Cucumber expression matches
    - match(pattern, step_text): Extract parameters from Cucumber expression
    """

Type Registry

Central registry for managing custom parameter types and their conversion functions.

class TypeRegistry:
    """
    Registry for managing custom parameter type converters.
    
    Methods:
    - register_type(name, func): Register a type converter function
    - convert(name, value): Convert value using registered type converter
    - get_type(name): Get registered type converter by name
    - clear(): Remove all registered type converters
    """

Built-in Types

Behave includes several built-in parameter types:

Numeric Types

# Integer type
@given('I have {count:d} items')
def step_impl(context, count):
    # count is automatically converted to int
    assert isinstance(count, int)

# Float type  
@given('the price is {amount:f} dollars')
def step_impl(context, amount):
    # amount is automatically converted to float
    assert isinstance(amount, float)

String Types

# Word type (no whitespace)
@given('the status is {status:w}')
def step_impl(context, status):
    # status contains no whitespace
    assert ' ' not in status

# Non-whitespace type
@given('the code is {code:S}')
def step_impl(context, code):
    # code contains no whitespace characters
    assert not any(c.isspace() for c in code)

Custom Type Examples

Boolean Type

def parse_bool(text):
    text = text.lower()
    if text in ('true', 'yes', '1', 'on', 'enabled'):
        return True
    elif text in ('false', 'no', '0', 'off', 'disabled'):
        return False
    else:
        raise ValueError(f"Cannot convert '{text}' to boolean")

register_type('bool', parse_bool)

@given('the feature is {enabled:bool}')
def step_impl(context, enabled):
    context.feature_enabled = enabled

Date Type

from datetime import datetime

def parse_date(text):
    try:
        return datetime.strptime(text, '%Y-%m-%d')
    except ValueError:
        try:
            return datetime.strptime(text, '%m/%d/%Y')
        except ValueError:
            raise ValueError(f"Cannot parse date: {text}")

register_type('date', parse_date)

@given('the event date is {date:date}')
def step_impl(context, date):
    context.event_date = date

Enum Type

from enum import Enum

class Priority(Enum):
    LOW = 'low'
    MEDIUM = 'medium'
    HIGH = 'high'

def parse_priority(text):
    try:
        return Priority(text.lower())
    except ValueError:
        raise ValueError(f"Invalid priority: {text}")

register_type('priority', parse_priority)

@given('the task priority is {priority:priority}')
def step_impl(context, priority):
    context.task_priority = priority

List Type

def parse_list(text):
    # Parse comma-separated values
    return [item.strip() for item in text.split(',')]

register_type('list', parse_list)

@given('the tags are {tags:list}')
def step_impl(context, tags):
    context.tags = tags  # ['tag1', 'tag2', 'tag3']

Advanced Pattern Matching

Optional Parameters

# Using parse syntax with optional parts
@given('I {action} {count:d} item(s)')
def step_impl(context, action, count):
    # Matches both "I add 1 item" and "I add 5 items"
    pass

Alternative Patterns

# Multiple patterns for same step
@given('I am logged in')
@given('I am authenticated') 
def step_impl(context):
    context.authenticated = True

Complex Regex Patterns

use_step_matcher("re")

@given(r'I have (\d+) (\w+)(?:s)? in my (\w+)')
def step_impl(context, count, item_type, container):
    count = int(count)
    # Handles pluralization automatically
    pass

Install with Tessl CLI

npx tessl i tessl/pypi-behave

docs

configuration.md

execution-model.md

fixtures.md

formatters.md

index.md

matchers-types.md

step-definitions.md

tile.json