You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否指定Behave测试表格中单元格的数据类型?

How to Specify Data Types for Behave Table Cells?

I wrote a test case to verify that an API returns expected content when handling bad requests:

Scenario: Unkown user response body properties contain expected content
Given I have a valid client auth token
And I request a user with an unknown "valid" uuid
And I get the response json
Then the expected fields should contain expected content
| field       | content               |
| statusCode  | 404                   |
| error       | Not Found             |
| message     | User record not found |

Here's the corresponding step implementation:

@then(u'the expected fields should contain expected content')
def step_impl(context):
    for row in context.table:
        received_content = str(context.request_json.get(row['field']))
        expected_content = row['content']
        assert_equal(received_content, expected_content)

I noticed that Behave automatically converts table row content to strings. The actual statusCode in the response is an integer, so I have to convert the response content to a string to make the assertion work. Is there a way to specify the data type for table cells in Behave? For example, mark the 404 in the content column as an integer so I don't have to convert the response content.

Great question! Behave doesn’t have built-in support for specifying data types directly in Gherkin tables, but there are several clean, flexible ways to handle type conversion in your step implementations. Here are a few practical approaches:

1. Field-Specific Type Mapping

If certain fields always use a specific type (like statusCode being an integer), you can define a fixed mapping of fields to their expected types. This keeps your Gherkin table unchanged while handling conversion behind the scenes:

from behave import then
from nose.tools import assert_equal

@then(u'the expected fields should contain expected content')
def step_impl(context):
    # Map fields to their required data types
    field_type_converters = {
        'statusCode': int,
        # Add other fields as needed (e.g., 'totalUsers': int, 'isVerified': bool)
    }

    for row in context.table:
        field = row['field']
        received_content = context.request_json.get(field)
        expected_str = row['content']

        # Use the converter for the field, default to string if no mapping exists
        converter = field_type_converters.get(field, str)
        
        try:
            expected_content = converter(expected_str)
        except ValueError:
            raise AssertionError(f"Failed to convert '{expected_str}' to {converter.__name__} for field '{field}'")

        assert_equal(received_content, expected_content)

2. Explicit Type Markers in Table Values

For more flexibility (like mixing types in the same column), add type prefixes to your table values and parse them in the step. This makes the type intent clear directly in your Gherkin:

First, update your Gherkin table with type markers:

Then the expected fields should contain expected content
| field       | content               |
| statusCode  | int:404               |
| error       | Not Found             |
| message     | User record not found |

Then implement a parser to handle these markers:

from behave import then
from nose.tools import assert_equal

def parse_typed_value(value):
    """Parse values with optional type prefixes (e.g., 'int:404' → 404)"""
    if value.startswith('int:'):
        return int(value.split(':', 1)[1])
    elif value.startswith('float:'):
        return float(value.split(':', 1)[1])
    elif value.lower() in ['true', 'false']:
        return value.lower() == 'true'
    # Default to string if no type marker is present
    return value

@then(u'the expected fields should contain expected content')
def step_impl(context):
    for row in context.table:
        received_content = context.request_json.get(row['field'])
        expected_content = parse_typed_value(row['content'])
        assert_equal(received_content, expected_content)

3. Add a Dedicated "Type" Column

For maximum readability, extend your table with a column that explicitly defines the data type for each row. This makes your Gherkin self-documenting for anyone reviewing the tests:

Update your Gherkin table:

Then the expected fields should contain expected content
| field       | type  | content               |
| statusCode  | int   | 404                   |
| error       | str   | Not Found             |
| message     | str   | User record not found |

Then adjust your step implementation to use this column:

from behave import then
from nose.tools import assert_equal

# Map type names to conversion functions
TYPE_MAP = {
    'int': int,
    'str': str,
    'float': float,
    'bool': lambda x: x.lower() == 'true'
}

@then(u'the expected fields should contain expected content')
def step_impl(context):
    for row in context.table:
        field = row['field']
        type_name = row['type']
        expected_str = row['content']

        converter = TYPE_MAP.get(type_name)
        if not converter:
            raise ValueError(f"Unsupported type '{type_name}' for field '{field}'")

        try:
            expected_content = converter(expected_str)
        except ValueError:
            raise AssertionError(f"Cannot convert '{expected_str}' to {type_name} for field '{field}'")

        received_content = context.request_json.get(field)
        assert_equal(received_content, expected_content)

All three methods work well—pick the one that best fits your test suite’s readability needs and flexibility requirements!

内容的提问来源于stack exchange,提问作者Jay Stringer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:49:10