接口测试框架1.0.0版本


技术:python+pytest+requests

要点:

1.专门封装ApiHttpbinGet、ApiHttpbinPost类,里面封装了get & post 的所有requests请求的请求方式和断言

2.test case里使用级联调用方法

3.对于不定性的参数使用**kwargs

4.最大的2个缺点:

  1)校验太单一

  2)代码冗余,比如run、validate,不论是post还是get方式都有,而且可以看requests里的requests()方法的源码,其中可以把method当作一个参数传进去

 版本1.0.0:

import json
import requests


class ApiHttpbinGet:
    url = "https://httpbin.org/get"
    method = "GET"
    headers = {"accept": "application/json"}
    params = {}

    def set_params(self, **kwargs):
        '''
        用来处理有params的get请求,而且为了保持在test case里调用的级联格式一致性,这里专门写一个注入params的方法,返回self对象
        :param kwargs: get请求体, **kwargs传入的必须是【xxx=xxx】的格式
        :return: 实例自身,用于级联操作
        '''
        self.params = kwargs.items()
        return self

    def run(self):
        """
        发送get方式的requests请求
        :return: 实例自身,用于级联操作
        """
        self.response = requests.get(self.url, headers=self.headers, params=self.params)
        return self

    def validate(self, key, excepted_value):
        """
        用于断言
        :return: 实例自身,用于级联操作
        """
        # print(self.response.__attrs__)
        # ['_content', 'status_code', 'headers', 'url', 'history', 'encoding','reason', 'cookies', 'elapsed', 'request']
        actual_value = getattr(self.response, key)
        assert actual_value == excepted_value
        return self


class ApiHttpbinPost:
    url = "https://httpbin.org/post"
    method = "POST"
    headers = {"accept": "application/json"}
    data = None
    json = None

    def set_request_data(self, **kwargs):
        """
        用来处理post请求的请求体,而且为了保持在test case里调用的级联格式一致性,这里专门写一个注入请求体的方法,返回self对象
        :param kwargs: post请求的请求体, **kwargs传入的必须是【json={xxx:yyy}】或者【data="xxxx"】的格式
        :return: 实例自身,用于级联操作
        """
        for k, v in kwargs.items():
            if 'data' == k:
                self.data = v
            elif 'json' == k:
                self.json = v
        return self

    def run(self):
        """
        发送post方式的requests请求
        :return: 实例自身,用于级联操作
        """
        self.response = requests.post(self.url, headers=self.headers, data=self.data, json=self.json)
        return self

    def validate(self, key, excepted_value):
        """
        用于断言
        :return: 实例自身,用于级联操作
        """
        # print(self.response.__attrs__) 
        # ['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request'] 
        actual_value = getattr(self.response, key)
        assert actual_value == excepted_value
        return self


class TestCore:
    def test_get(self):
        r = requests.get("https://httpbin.org/get", headers={"accept": "application/json"})
        assert r.status_code == 200

    def test_get_new(self):
        ApiHttpbinGet().run().validate('status_code', 200)

    def test_get_params_new(self):
        ApiHttpbinGet().set_params(abc=123, xyz=345).run().validate('url', 'https://httpbin.org/get?abc=123&xyz=345')

    def test_post_json(self):
        r = requests.post("https://httpbin.org/post",
                          headers={"accept": "application/json"},
                          json={"a": "1"})
        assert r.status_code == 200
        assert r.json()["data"] == '{"a": "1"}'

    def test_post_json_new(self):
        request_body = {"a": "1"}
        ApiHttpbinPost().set_request_data(json=request_body).run().validate('status_code', 200)

    def test_post_data(self):
        data = {"a": "1"}
        r = requests.post("https://httpbin.org/post",
                          headers={"accept": "application/json"},
                          data=json.dumps(data))
        assert r.status_code == 200
        assert r.json()["data"] == '{"a": "1"}'

    def test_post_data_new(self):
        data = {"a": "1"}
        ApiHttpbinPost().set_request_data(data=json.dumps(data)).run().validate('status_code', 200) 

版本1.0.1:

抽象出基类BasicApi,基类中实现类获取params、获取data、发送请求、返回结果校验的基础功能

各类请求的类都集成这个基类

import json
import requests


class BasicApi:
    url = None
    method = None
    headers = {"accept": "application/json"}
    params = {}
    data = None
    json = None

    def set_params(self, **kwargs):
        '''
        用来处理有params的请求
        :param kwargs: 请求参数, **kwargs传入的必须是【xxx=xxx】的格式
        :return: 实例自身,用于级联操作
        '''
        self.params = kwargs.items()
        return self

    def set_data(self, **kwargs):
        """
        用来处理post请求的请求体,而且为了保持在test case里调用的级联格式一致性,这里专门写一个注入请求体的方法,返回self对象
        :param kwargs: post请求的请求体, **kwargs传入的必须是【json={xxx:yyy}】或者【data="xxxx"】的格式
        :return: 实例自身,用于级联操作
        """
        for k, v in kwargs.items():
            if 'data' == k:
                self.data = v
            elif 'json' == k:
                self.json = v
        return self

    def run(self):
        """
        发送requests请求
        :return: 实例自身,用于级联操作
        """
        self.response = requests.request(self.method, self.url, headers=self.headers, params=self.params,
                                         data=self.data, json=self.json)
        return self

    def validate(self, key, excepted_value):
        """
        用于断言
        :return: 实例自身,用于级联操作
        """
        actual_value = getattr(self.response, key)
        assert actual_value == excepted_value
        return self


class ApiHttpbinGet(BasicApi):
    url = "https://httpbin.org/get"
    method = "GET"


class ApiHttpbinPost(BasicApi):
    url = "https://httpbin.org/post"
    method = "POST"


class TestCore:

    def test_get(self):
        ApiHttpbinGet().run().validate('status_code', 200)

    def test_get_params(self):
        ApiHttpbinGet().set_params(abc=123, xyz=345).run().validate('url', 'https://httpbin.org/get?abc=123&xyz=345')

    def test_post_json(self):
        request_body = {"a": "1"}
        ApiHttpbinPost().set_data(json=request_body).run().validate('status_code', 200)

    def test_post_data(self):
        data = {"a": "1"}
        ApiHttpbinPost().set_data(data=json.dumps(data)).run().validate('status_code', 200)