线下第三期_接口测试进阶_20181014

课前准备

上节课作业: https://testerhome.com/topics/16170

SessionFilter

使用与代码剖析

数据驱动

导入依赖


        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-csv</artifactId>
            <version>2.8.8</version>
        </dependency>

csv驱动

package offline3;

import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.equalTo;


@RunWith(Parameterized.class)
public class AssertionTestData {
    @Rule
    public ErrorCollector collector = new ErrorCollector();


/*    public static List<TestData> data(){
        ArrayList<TestData> datas=new ArrayList<>();
        datas.add(new TestData(1, 2));
        datas.add(new TestData(2, 2));
        return datas;
    }*/

    @Parameterized.Parameters
    public static List<TestData> dataCSV() throws IOException {
        return readFromCSV();
    }


    public static List<TestData> readFromCSV() throws IOException {
        ArrayList<TestData> data=new ArrayList<TestData>();

        CsvMapper mapper = new CsvMapper();
        CsvSchema schema = mapper.schemaFor(TestData.class);
        //mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        File csvFile = new File(AssertionTestData.class.getResource("../data/testdata.csv").getFile()); // or from String, URL etc
        MappingIterator<TestData> it = mapper.readerFor(TestData.class).with(schema).readValues(csvFile);
        while (it.hasNext()) {
            TestData row = it.next();
            data.add(row);
        }
        return data;
    }

    @Parameterized.Parameter
    public TestData data;

    @Test
    public void assertions(){
        collector.checkThat(data.getReal(), equalTo(data.getExpect()));
    }

}

数据模型

package offline3;

public class TestData {


    public int getReal() {
        return real;
    }

    public void setReal(int real) {
        this.real = real;
    }

    private int real;

    public int getExpect() {
        return expect;
    }

    public void setExpect(int expect) {
        this.expect = expect;
    }

    private int expect;

}

数据文件

1,2
3,4
1,1
2,2
3,3
3,5

YAML与json数据

    public static List<TestData> readFromYAML() throws IOException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        List<TestData> data = mapper.readValue(
                new File(AssertionTestData.class.getResource("/data/testdata.yaml").getFile()),
                new TypeReference<List<TestData>>(){}
        );

        return data;
    }

    public static List<TestData> readFromJSON() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        List<TestData> data = mapper.readValue(
                new File(AssertionTestData.class.getResource("/data/testdata.json").getFile()),
                new TypeReference<List<TestData>>(){}
        );

        return data;
    }

YAML数据源

- real: 1
  expect: 1
  real2: 2
  expect2: 2
- real: 1
  expect: 2
  real2: 2
  expect2: 2
- real: 1
  expect: 1
  real2: 2
  expect2: 2
- real: 1
  expect: 1
  real2: 2
  expect2: 3

JSON数据源

[
  {
    "real": 1,
    "expect": 1,
    "real2": 2,
    "expect2": 4
  },
  {
    "real": 1,
    "expect": 2,
    "real2": 2,
    "expect2": 2
  }
]

读取配置文件

    public static void write(String filePath){
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        try {
            mapper.writeValue(new File(filePath), new MeiTuanConfig());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static MeiTuanConfig load(String filePath){
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        MeiTuanConfig conf=new MeiTuanConfig();
        try {
            conf=mapper.readValue(new File(filePath), MeiTuanConfig.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return conf;
    }

测试用例管理

三种至关重要的顺序控制

  • 套件级别的顺序控制
  • 继承关系里的初始化顺序
  • 单个类里的执行顺序


企业微信演练

Swagger

Dubbo

小作业1

创建一个三层的继承关系,所有的Class里都添加上类级别的初始化BeforeClass和方法级别的初始化Before,打印下所有方法的执行流程。
A->B->C->3个用例

作业2

读取一个三行两列的csv数据,这个数据里是字符串,断言两个字符串是否相等

作业3

从YAML文件里读取3个数据,两个数字,一个字符串。构建一个数据驱动的测试用例,根据两个数字的相加,判断是否等于字符串。

作业4

完成企业微信的接口测试用例体系。提前演练,下节课重点实训。把完整的项目代码上传到github并把仓库地址贴到回复里。

拔高题

做一个小的基于yaml的接口测试工具,支持发送请求和断言。

- given:
    queryParam:
    -  key: value
    headers:
    - key: "content-type"
      value: "json"
    request: get/post
  when:
    request: get/post
    url: "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
  then:
    statusCode: 200
    body:
      - errcode: 0
- given:
    queryParam:
    -  key: value
    header:
    - key: "content-type"
      value: "json"
    request: get/post
  when:
    request: get/post
    url: "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
  then:
    statusCode: 200
    body:
    - errcode: 0
public class HttpTest {
    static List<HttpTestStep> testcase;
    @BeforeClass
    public static void beforeClass(){
        //testcase=load(yaml)
    }
    @Test
    public void run(){
        for(HttpTestStep step: testcase){
            RequestSpecification requestSpecification=given();
            if(step.given.request=="get"){
              requestSpecification.when().get(step.given.url);
            }
            requestSpecification.then().statusCode(200);
        }
    }
}