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

如何通过编程从Feature File提取所有Scenario及指定Scenario的assertions?

从Cucumber Feature文件提取Scenario及断言的简便实现

为什么不推荐模式匹配(正则)

别用正则表达式硬匹配,Feature文件有各种语法细节(比如Scenario Outline、嵌套注释、步骤换行、多语言关键词),正则很容易漏判或误判,后期维护成本极高,不如用专门的语法解析工具。

简便实现:用官方Gherkin解析库

Gherkin是Cucumber的官方语法解析库,支持Java、Python、JS等多语言,能准确解析Feature文件的结构化数据,直接提取你需要的内容,是最靠谱的方案。

Python 实现示例

首先安装依赖:

pip install gherkin-official

代码实现:

from gherkin.parser import Parser
from gherkin.token_scanner import TokenScanner

def parse_feature_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()
    scanner = TokenScanner(content)
    parser = Parser()
    return parser.parse(scanner)

# 获取所有Scenario(含Scenario Outline)的名称列表
def get_all_scenarios(feature_data):
    scenarios = []
    for element in feature_data['feature']['children']:
        if element['type'] == 'Scenario':
            scenarios.append(element['name'])
        elif element['type'] == 'ScenarioOutline':
            scenarios.append(element['name'])
    return scenarios

# 提取指定Scenario的所有断言步骤
# 可根据项目规则调整断言关键词(比如should/assert/verify等)
def get_scenario_assertions(feature_data, target_scenario):
    assertions = []
    for element in feature_data['feature']['children']:
        if element['type'] in ['Scenario', 'ScenarioOutline'] and element['name'] == target_scenario:
            for step in element['steps']:
                step_text = step['text'].lower()
                if any(keyword in step_text for keyword in ['should', 'assert', 'verify', 'be equal to', 'match']):
                    assertions.append(f"{step['keyword']} {step['text']}")
            break
    return assertions

# 使用示例
if __name__ == '__main__':
    feature_path = './test.feature'
    feature = parse_feature_file(feature_path)
    
    # 打印所有Scenario
    print("所有Scenario列表:")
    for sc_name in get_all_scenarios(feature):
        print(f"- {sc_name}")
    
    # 提取指定Scenario的断言
    target = "用户成功登录后跳转至首页"
    print(f"\n{target} 的断言步骤:")
    for assert_step in get_scenario_assertions(feature, target):
        print(f"- {assert_step}")

Java 实现示例

添加Maven依赖:

<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>gherkin</artifactId>
    <version>26.0.0</version>
</dependency>

代码实现:

import io.cucumber.gherkin.GherkinParser;
import io.cucumber.gherkin.GherkinTokenScanner;
import io.cucumber.messages.types.Feature;
import io.cucumber.messages.types.Scenario;
import io.cucumber.messages.types.ScenarioOutline;
import io.cucumber.messages.types.Step;

import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class FeatureProcessor {

    // 解析Feature文件
    public static Feature parseFeature(String filePath) throws Exception {
        try (InputStreamReader reader = new InputStreamReader(new FileInputStream(filePath), "UTF-8")) {
            GherkinTokenScanner scanner = new GherkinTokenScanner(reader);
            return GherkinParser.parse(scanner).getFeature().get();
        }
    }

    // 获取所有Scenario名称
    public static List<String> getAllScenarioNames(Feature feature) {
        List<String> names = new ArrayList<>();
        feature.getChildren().forEach(child -> {
            child.getScenario().ifPresent(scenario -> names.add(scenario.getName()));
            child.getScenarioOutline().ifPresent(outline -> names.add(outline.getName()));
        });
        return names;
    }

    // 提取指定Scenario的断言步骤
    public static List<String> getAssertionsForScenario(Feature feature, String targetName) {
        List<String> assertions = new ArrayList<>();
        for (Feature.FeatureChild child : feature.getChildren()) {
            // 处理普通Scenario
            if (child.getScenario().isPresent()) {
                Scenario scenario = child.getScenario().get();
                if (scenario.getName().equals(targetName)) {
                    collectAssertionSteps(scenario.getSteps(), assertions);
                    break;
                }
            }
            // 处理Scenario Outline
            else if (child.getScenarioOutline().isPresent()) {
                ScenarioOutline outline = child.getScenarioOutline().get();
                if (outline.getName().equals(targetName)) {
                    collectAssertionSteps(outline.getSteps(), assertions);
                    break;
                }
            }
        }
        return assertions;
    }

    // 筛选断言步骤(可自定义关键词规则)
    private static void collectAssertionSteps(List<Step> steps, List<String> assertions) {
        String[] assertionKeywords = {"should", "assert", "verify", "be equal to", "match"};
        for (Step step : steps) {
            String stepText = step.getText().toLowerCase(Locale.ROOT);
            for (String keyword : assertionKeywords) {
                if (stepText.contains(keyword)) {
                    assertions.add(step.getKeyword() + step.getText());
                    break;
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String featurePath = "./src/test/resources/test.feature";
        Feature feature = parseFeature(featurePath);

        // 输出所有Scenario
        System.out.println("所有Scenario列表:");
        getAllScenarioNames(feature).forEach(name -> System.out.println("- " + name));

        // 输出指定Scenario的断言
        String targetScenario = "用户成功登录后跳转至首页";
        System.out.println("\n" + targetScenario + " 的断言步骤:");
        getAssertionsForScenario(feature, targetScenario).forEach(step -> System.out.println("- " + step));
    }
}

关键说明

  • 断言的判断逻辑可以根据项目规则灵活调整:比如如果项目里断言步骤统一用Then关键词,或者有特定业务术语,可以直接匹配这些规则,不用局限于示例里的关键词。
  • 官方解析库会自动处理Feature文件的注释、空行、Scenario Outline等特殊情况,比正则表达式稳定得多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:38