如何用Junit5玩出参数化测试的新花样?

简介

这是之前一篇文章《用junit5编写一个类ZeroCode的测试框架》的续集。主要将在之前工作的基础上,围绕参数化测试展开。 框架主要设计点:

  • 一个用例是一个测试文件
  • 一个用例集是一个目录
  • 用例全部在文件中呈现,不需要写代码
  • 主要使用的是 Junit5提供的@ParameterizedTest

引入参数化

为了能使用Junit5中重新设计的参数化测试解决方案,需要额外在pom.xml中引入junit-jupiter-params

<dependency>
  <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.5.2</version>
    <scope>test</scope>
</dependency>

用那种参数?

在一般的参数化测试介绍中,通常的方案是将一个文件作为数据源,如一个单一的csv文件,然后其中的某一行作为一个用例。而在我们的方案中,我们需要将整个给定目录中的csv文件作为测试用例集进行遍历执行。在评估了junit-jupiter-params所提供的下列全新的注解之后,

@ValueSource
@EnumSource
@MethodSource
@CsvSource
@CsvFileSource
@ArgumentsSource

笔者选择了@MethodSource来实现。

实现

首先来看一下@ParameterizedTest注解的用例样例

package com.demo.junit5;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import com.demo.junit5.bean.TestStep;
import com.demo.junit5.runner.MockRunner;
import com.demo.junit5.runner.Runner;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TestSuite {
    private static final String basePath=".\\tests";
    private Runner runner = new MockRunner();
    //@Scenario(value=".\\tests\\demo1\\sample.csv")
    @ParameterizedTest
    @MethodSource("getFiles")
    public void sampleTest(String testCase)   {
        log.info("now running:'{}'",testCase);
        try {
            runCase(runner,testCase);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上述用例的意思是,通过 @MethodSource("getFiles")来获取一组参数,并依次作为testCase入参来执行sampleTest方法,从而实现所谓的参数化测试。 这里的关键是,我们需要提供一个叫做getFiles的方法。

    private static List<String> getFiles(){
        try {
            Stream<Path> walk=Files.walk(Paths.get(basePath));
                List<String> result=walk.map(x -> x.toString())
                                        .filter(f -> f.endsWith(".csv"))
                                        .collect(Collectors.toList());
                return result;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        
    }

这个方法就是去完成扫描给定目录下所有的csv文件,并将文件的完整目录纳入一个集合中并返回。 同时,我们也需要一个执行器去实现用例的执行。一个简单的样例如下:

    private static void runCase(Runner runner,String testCase) throws IOException {
        Reader reader = Files.newBufferedReader(Paths.get(testCase));
        CsvToBean<TestStep> csvToBeans = new CsvToBeanBuilder(reader)
                        .withType(TestStep.class)
                        .withIgnoreLeadingWhiteSpace(true)
                        .withSeparator(',')
                        .build();
        Iterator<TestStep> csvIterator = csvToBeans.iterator();
        while(csvIterator.hasNext()) {
            TestStep testStep =csvIterator.next();
            runner.run(testStep);
        }
        
    }
}

执行效果

在tests目录下,简单复制几个文件和目录作为案例,然后使用之前编写的MockRunner来执行。

image.png

执行结果如下:

image.png

部分执行日志:

image.png

小结

对于不想写代码来实现自动化测试的团队来说,通过编写csv等文本文件的方式来定义用例,并由测试开发或者开发人员来根据约定提供Runner及关键字,也是一种有效的自动化实施方式。本文提供的简单案例,可以作为参考。

下一篇
举报

扫码关注云+社区

领取腾讯云代金券