一种基于swagger 2.0 yaml文件的接口异常用例生成算法,单因子变量法

详细解决方案

一、设计思路

基于 Swagger 2.0 的 YAML 定义,为每个参数生成两类测试用例:

  1. 正常用例:所有参数均符合约束。
  2. 异常用例:仅一个参数违反约束,其他参数正常,且每个参数需覆盖所有可能的异常场景。
二、实现步骤
  1. 解析 Swagger 文件
    使用 SnakeYAML 解析 YAML,提取参数定义(类型、约束、是否必填等)。
  2. 生成正常值
    根据参数类型和约束生成合法值。
  3. 生成异常值
    针对每个参数的所有约束,生成违反每个约束的非法值。
  4. 组合测试用例
    每个异常参数生成一组用例,其他参数保持正常。
  5. 记录元数据
    记录异常参数名称、违反的约束类型、非法值。

完整 Java 实现代码

1. 依赖配置
<dependencies>
    
    <dependency>
        <groupId>org.yamlgroupId>
        <artifactId>snakeyamlartifactId>
        <version>1.33version>
    dependency>
dependencies>
2. 核心代码结构
参数定义模型类
public class SwaggerParameter {
    private String name;
    private String in;
    private String type;
    private boolean required;
    private Integer min;
    private Integer max;
    private String pattern;
    private List<String> enumValues;
    // Getters and Setters
}
测试用例元数据类
public class TestCaseMetadata {
    private String fieldName;
    private String constraintType;
    private Object invalidValue;
    // Getters and Setters
}
测试用例生成器
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
import java.util.*;

public class SwaggerTestCaseGenerator {

    // 1. 解析 Swagger YAML 文件
    public List<SwaggerParameter> parseSwagger(String yamlPath) {
        Yaml yaml = new Yaml();
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(yamlPath);
        Map<String, Object> swaggerMap = yaml.load(inputStream);
        // 解析参数(示例仅提取全局 parameters)
        List<Map<String, Object>> params = (List<Map<String, Object>>) swaggerMap.get("parameters");
        List<SwaggerParameter> parameters = new ArrayList<>();
        for (Map<String, Object> param : params) {
            SwaggerParameter p = new SwaggerParameter();
            p.setName((String) param.get("name"));
            p.setType((String) param.get("type"));
            p.setMin((Integer) param.get("minimum"));
            p.setMax((Integer) param.get("maximum"));
            p.setPattern((String) param.get("pattern"));
            p.setEnumValues((List<String>) param.get("enum"));
            parameters.add(p);
        }
        return parameters;
    }

    // 2. 生成所有异常测试用例
    public List<Pair<Map<String, Object>, TestCaseMetadata>> generateTestCases(List<SwaggerParameter> params) {
        List<Pair<Map<String, Object>, TestCaseMetadata>> cases = new ArrayList<>();
        Map<String, Object> baseCase = generateValidCase(params);

        for (SwaggerParameter param : params) {
            // 生成该参数的所有异常值及其元数据
            List<Pair<Object, TestCaseMetadata>> invalidValues = generateInvalidValues(param);
            for (Pair<Object, TestCaseMetadata> pair : invalidValues) {
                Map<String, Object> testCase = new HashMap<>(baseCase);
                testCase.put(param.getName(), pair.getLeft());
                cases.add(Pair.of(testCase, pair.getRight()));
            }
        }
        return cases;
    }

    // 3. 生成正常参数值
    private Map<String, Object> generateValidCase(List<SwaggerParameter> params) {
        Map<String, Object> validCase = new HashMap<>();
        for (SwaggerParameter param : params) {
            validCase.put(param.getName(), generateValidValue(param));
        }
        return validCase;
    }

    // 4. 根据参数类型生成合法值
    private Object generateValidValue(SwaggerParameter param) {
        switch (param.getType()) {
            case "string":
                return generateValidString(param);
            case "integer":
                return generateValidInteger(param);
            case "boolean":
                return true;
            default:
                return "default";
        }
    }

    // 5. 生成字符串合法值
    private String generateValidString(SwaggerParameter param) {
        if (param.getEnumValues() != null && !param.getEnumValues().isEmpty()) {
            return param.getEnumValues().get(0);
        }
        return "valid_string";
    }

    // 6. 生成整数合法值
    private Integer generateValidInteger(SwaggerParameter param) {
        int min = param.getMin() != null ? param.getMin() : 1;
        int max = param.getMax() != null ? param.getMax() : 100;
        return (min + max) / 2;
    }

    // 7. 生成参数的所有非法值及元数据
    private List<Pair<Object, TestCaseMetadata>> generateInvalidValues(SwaggerParameter param) {
        List<Pair<Object, TestCaseMetadata>> invalidValues = new ArrayList<>();
        TestCaseMetadata metadata = new TestCaseMetadata();
        metadata.setFieldName(param.getName());

        // 根据参数类型生成不同非法值
        switch (param.getType()) {
            case "string":
                if (param.getEnumValues() != null) {
                    metadata.setConstraintType("enum");
                    invalidValues.add(Pair.of("invalid_enum_value", metadata));
                }
                if (param.getPattern() != null) {
                    metadata.setConstraintType("pattern");
                    invalidValues.add(Pair.of("invalid@pattern", metadata));
                }
                break;
            case "integer":
                if (param.getMin() != null) {
                    metadata.setConstraintType("min");
                    invalidValues.add(Pair.of(param.getMin() - 1, metadata));
                }
                if (param.getMax() != null) {
                    metadata.setConstraintType("max");
                    invalidValues.add(Pair.of(param.getMax() + 1, metadata));
                }
                metadata.setConstraintType("type");
                invalidValues.add(Pair.of("invalid_integer", metadata));
                break;
            case "boolean":
                metadata.setConstraintType("type");
                invalidValues.add(Pair.of("not_boolean", metadata));
                break;
        }
        return invalidValues;
    }
}
3. 使用示例
public class Main {
    public static void main(String[] args) {
        SwaggerTestCaseGenerator generator = new SwaggerTestCaseGenerator();
        List<SwaggerParameter> params = generator.parseSwagger("api.yaml");
        List<Pair<Map<String, Object>, TestCaseMetadata>> testCases = generator.generateTestCases(params);

        for (Pair<Map<String, Object>, TestCaseMetadata> testCase : testCases) {
            System.out.println("Test Case: " + testCase.getLeft());
            System.out.println("Metadata: " + testCase.getRight());
        }
    }
}

关键逻辑说明

  1. 参数解析
    通过 parseSwagger 方法解析 YAML 中的参数定义,提取类型、最小值、最大值等约束。

  2. 正常值生成

    • 字符串:优先取枚举值,否则生成固定合法值。
    • 整数:取最小值和最大值的中间值。
  3. 异常值生成

    • 字符串:违反枚举、正则、长度约束。
    • 整数:小于最小值、大于最大值、非整数类型。
    • 布尔值:非布尔类型。
  4. 用例组合
    每个异常用例仅修改一个参数的值,其他参数保持正常。


用例数量估算

假设一个接口有 20 个参数,类型分布如下:

类型 参数数量 每个参数平均异常场景数 总用例数
String 12 3 (枚举/正则/长度) 36
Integer 4 3 (min/max/类型) 12
Long 2 3 (同上) 6
Boolean 1 1 (类型错误) 1
Float 1 3 (min/max/类型) 3

总用例数 = 36 + 12 + 6 + 1 + 3 = 58


扩展性建议

  1. 支持更多类型
    添加 generateValidNumber() 处理浮点数,增加对 format: double 的支持。
  2. 复杂约束
    使用正则引擎解析 pattern,动态生成非法字符串。
  3. 依赖注入
    集成类似 Generex 的库生成符合正则的随机字符串。

你可能感兴趣的:(java,测试用例)