数据驱动测试,减少重复代码

举报
冰释流水 发表于 2021/08/17 17:19:41 2021/08/17
【摘要】 ​ 最近在参加一个架构解耦的项目,在里面开发了多个工具,因为工具是构建过程中所有服务都会使用,所以对质量要求比较高。做事前,三思而后行,为了未来这个工具质量不至于恶化的比较严重,我准备交付这个工具前,一定要把工具用例写好。为后面承接该工具的兄弟做地实在的建设。​ 因为是针对工具进行测试,工具类似一个函数一样,每个测试用例都需要定义输入和输出,用例整理完成后,发现:如果一个用例一个用例地写...

参数化测试

​ 最近在参加一个架构解耦的项目,在里面开发了多个工具,因为工具是构建过程中所有服务都会使用,所以对质量要求比较高。做事前,三思而后行,为了未来这个工具质量不至于恶化的比较严重,我准备交付这个工具前,一定要把工具用例写好。为后面承接该工具的兄弟做地实在的建设。

​ 因为是针对工具进行测试,工具类似一个函数一样,每个测试用例都需要定义输入和输出,用例整理完成后,发现:如果一个用例一个用例地写,手会写断,而且存在大量的冗余代码,难以维护,网上寻思半天,发现“参数化测试”可以解决我的问题

​ 废话不多说,言归正传。

​ 参数化测试,侠义来讲,是指将定义测试过程,通过输入不同参数,得到具体的不同用例;广义来讲,是指的一种数据驱动测试的设计思想。总之,解决的是软件中基本的冗余问题,是通过将测试架构分层,将测试因子组合抽象为测试数据,将测试过程抽象为测试行为,最后将数据和行为叠加在一起,形成丰富全面的测试用例

​ 参数化测试可以为整个软件测试,带来如下好处:

  1. 测试代码更简洁,更易维护。显而易见,测试代码沉淀的是公共的测试过程,不会包含其他冗余的数据代码。
  2. 用例开发更高效。通过新增数据,即可快速增加新的用例。

当然,按辩证的唯物主义思想来看,任何事物都有两面性,参数化测试,实际也存在一些“坏处”:

  1. 参数化测试,使得测试软件架构分层,本身复杂度增加,数据与行为的边界存在约定的关联关系。
  2. 对用例开发质量要求更高。整个项目开发过程中,我修改了多次测试行为实现,多次引发大批量的测试用例失败,😓
  3. 扩展性有限,数据、行为分离的测试架构,也给整个测试定义了各种规则,所有用例必须在既定的规则世界中存活,打破规则的用例,无法寄生在这个“世界“中。

以上都比较虚,纯理论,马克思主义告诉我们,实践是检验真理的唯一标准。我们来点实在的。

因为是针对于工具进行测试,工具大体作用是输入一些文件和参数,输出新的文件。参考linux文件系统架构,我将所有测试中设计的参数,都文件化,按目录组织每个用例。

工具使用方法:

Usage: modelfriend [--dsttype=<dstType>] --model=<modelName> -s=<originFile>
                   --scene=<sceneName> -t=<targetFile>
make new models from origin models on specified scense.
      --dsttype=<dstType>   Output the new model file with specified file type,
                              Values:xml, json, ini, properties, macro_ini
      --model=<modelName>   The model driver which is used to read or write
                              file.
  -s, --source=<originFile> The origin file which is used to make new models
                              file.
      --scene=<sceneName>   The directory which has stored with the scene cfg
                              files.
  -t, --target=<targetFile> The new model file.

通用测试过程:

#!/bin/sh
pwd;
pushd $1;
# 输入参数,通过工具处理原始文件,得到新的文件
java -jar $2 -s $3 -t $4 --model=$5 --scene=$6;
# 检查新的文件,是否与期望的文件是一致
diff $7 $8;
[ $? -eq 0 ] || exit 1;
popd;

测试数据设计:

  1. 每一个目录都是一个测试用例。
  2. 目录名称按固定格式组织,携带了对应的model参数,便于用例设计和管理
  3. 目录下,文件命名按照固定规则命名(src…,dst…)src…表示文件作为工具的源文件,dst…表示文件作为工具输出的目标文件,edge作为工具的参数配置

最终,通过如下代码,定义测试过程:

public class ModelToolTestSuite {
    private static final String[] fileters = {}; //"_mml.model_"

    private static boolean isMatch(String name) {
        if(fileters.length == 0) {
            return true;
        }
        return Arrays.asList(fileters).stream().anyMatch(name::contains);
    }

    @Parameterized.Parameters(name = "{index} : {0}")
    public static Collection<Object[]> data() {

        List<Object[]> parameters = new ArrayList<>();
        try {
            File root = new File(ModelToolTestSuite.class.getClassLoader().getResource(".").toURI());
            for( File dir : root.listFiles()) {

                if(dir.isDirectory() && dir.getName().contains("case_") && isMatch(dir.getName())) {
                    String[] pars = {dir.getName()};
                    parameters.add(pars);
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return parameters;
    }

    @Parameterized.Parameter(0)
    public String caseName;

    @Test
    public void RunTest()
    {
        ModelToolTestBean d = ModelToolTestHelper.MakeTestCaseData(caseName);
        Assert.assertNotNull(d);
        Boolean isOk = ModelToolTestHelper.RunWithData(d);
        Assert.assertTrue(isOk);
    }
}

整个测试结果如下:

(完结)

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。