python接口自动化学习(一)

最简单最基本的接口自动化测试框架,python+request+unittest
文件结构
python接口自动化学习(一)_第1张图片

1.创建config.ini配置文件

config.ini中存放HTTP、email、数据库等信息,可以在email中加入on_off=on; =on 则不发邮件。

[DATABASE]
# ip地址
host = 50.23.190.57
# 用户名
username = xxxxxx
# 密码
password = ******
# 端口
port = 3306
# 数据库名称
database = flychord

[HTTP]
# 协议
scheme=http
#地址
baseurl = 192.168.X.XX
# 端口
port =8080
# 超时时间
timeout = 10.0
headers = {'POST http': '//XXXX.XXXX.com/member/memberchpoexercise/addgamesexercise/ HTTP/1.1','Expect': '100-continue', 'X-Unity-Version': '2018.3.1f1','Content-Type': 'application/x-www-form-urlencoded', 'token': '467cb87f1e5f7a3d10ed18d8b41842c5','version': '1.0','timestamp': '1564046939039','encrypt': '0','ports': 'AU', 'os': 'android','Content-Length': '103','User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 7.0; KOB-W09 Build/HUAWEIKOB-W09)','Host': 'flychordtest.pianosedu.com', 'Connection': 'Keep-Alive','Accept-Encoding': 'gzip'}






[EMAIL]
mail_host = smtp.163.com
mail_user = xxx@163.com
mail_pass = *********
mail_port = 25
sender = xxx@163.com
receiver = xxxx@qq.com/xxxx@qq.com
subject = python
content = "All interface test has been complited\nplease read the report file about the detile of result in the attachment."
testuser = Someone
on_off = 1

2.创建getPathInfo.py文件

用于获取某路径下文件的绝对路径

import os
def get_Path():
    path = os.path.split(os.path.realpath(__file__))[0]
    return path

3.创建readConfig.py文件

用于读取config.ini中的配置信息

import os
from FlychordInterfaceTest import getPathInfo
import configparser  # 引入我们自己的写的获取路径的类

path = getPathInfo.get_Path()  # 调用实例化,path:D:\Testing\jiaoben\FlychordInterfaceTest
config_path = os.path.join(path,'config.ini')  # 在path路径下再加一级,configPath:D:\Testing\jiaoben\FlychordInterfaceTest\config.ini
config = configparser.ConfigParser()  # 调用外部的读取配置文件的方法
config.read(config_path, encoding='utf-8')  # 打开配置文件


def get_email(name):
    value = config.get("EMAIL", name)
    return value


def get_http(name):
    value = config.get("HTTP", name)
    return value


def get_mysql(name):  # 写好,留以后备用。但是因为我们没有对数据库的操作,所以这个可以屏蔽掉
    value = config.get("DATABASE", name)
    return value

# print(type(get_http('headers')))

4.创建readExcel.py

用于读取用例文档或接口文档

import xlrd
import os
import json
from FlychordInterfaceTest import getPathInfo


class Excel():
    # 初始化方法 参数type:为r是读取excel,参数file_name是将要读取的文件,参数index是将要读取的那一页
    def __init__(self, file_name, index):
        path = getPathInfo.get_Path()
        excel_path = os.path.join(path, 'file', file_name)
        # 打开文件
        self.data = xlrd.open_workbook(excel_path)
        # 选取需要读取数据的那一页
        self.sheet1 = self.data.sheet_by_index(index)
        # 获得行数和列数
        self.rows1 = self.sheet1.nrows
        self.cols1 = self.sheet1.ncols
        # 装载所有数据的list
        self.listvalue = []

    # 读取数据
    def read(self):
        # 从第二行开始读取
        for i in range(1, self.rows1):
            value = []
            for j in range(0, self.cols1):
                # 读取表格内容按行,列取值
                '''ctype: 0 empty, 1 string, 2 number, 3 date, 4 boolean, 5 error'''
                ctype = self.sheet1.cell(i, j).ctype  # 获取数据的类型
                cell = self.sheet1.cell(i, j).value  # 获取数据的值
                # 判断Excel数据是否为整型
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                # 判断Excel数据是否为时间格式
                elif ctype == 3:
                    # 转成datetime对象
                    from datetime import datetime
                    from xlrd import xldate_as_tuple
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y-%d-%m %H:%M:%S')
                # 判断Excel数据是否为布尔值
                elif ctype == 4:
                    cell = True if cell == 1 else False
                # 存储到数组
                value.append(cell)
            self.listvalue.append(value)
        return self.listvalue


# 将元素和链接表处理为json格式方便进行查询
def element_tojson(element):
    elements = {}
    # 讲元素和接口等信息组成key和value的形式方便进行查询
    for e in element:
        elements[e[0]] = {'type': e[1], 'url': e[2]}
    return elements


# 将元素和链接表处理为list格式方便进行查询
def element_list(element):
    elements = []
    for e in element:
        a = []
        a.append(e[1])
        a.append(e[4])
        a.append(e[6])
        a.append(to_json(e[9]))
        a.append(to_json(e[10]))
        elements.append(a)
    return elements


def to_json(b):
	# 过滤换行和空格
    a = b.replace('\n', '').replace(' ', '')
    # 判断是否为josn数据
    if a[0] == '{':
        params = json.loads(a)
        # print(params)
        return params
    else:
        # print(a)
        return a


if __name__ == '__main__':
    excel = Excel('DATA.xlsx', 0).read()
    for i in range(0, 3):
        to_json(excel[i][10])
    # print(excel.read()[0][1])  # 用例标题
    # print(excel.read()[0][4])  # 请求方法
    # print(excel.read()[0][6])  # 接口路径
    # print(excel.read()[0][9])  # 接口请求参数
    # print(excel.read()[0][10])  # 接口返回参数

5.创建configHttp.py文件

先创建common文件夹,confighttp.py用于等着接口请求

import requests


def send_post(url, data, headers):
    result = requests.post(url=url, headers=headers, data=data).json()
    return result


def send_get(url, data, headers):
    result = requests.get(url=url, headers=headers, params=data).json()
    return result


def run_main(method, url=None, data=None, headers=None):  # 定义一个run_main函数,通过传过来的method来进行不同的get或post请求
    result = None
    method = method.lower()
    if method == 'post':
        result = send_post(url, data, headers)
    elif method == 'get':
        result = send_get(url, data, headers)
    else:
        print("method值错误!!!")
    return result


if __name__ == '__main__':
    result1 = run_main('get', 'http://192.168.1.155:8080//public/timestamp')
    print(result1)

6.创建getURL.py文件

获取URL组成请求地址

from FlychordInterfaceTest import readConfig


def get_url(interface):
    if readConfig.get_http('port') is None:
        url = readConfig.get_http('scheme') + '://' + readConfig.get_http('baseurl') + interface
    else:
        url = readConfig.get_http('scheme') + '://' + readConfig.get_http('baseurl') + ":" + readConfig.get_http(
            'port') + interface
    return url

7.创建case测试用例

简易版:

import unittest  # 导包
from FlychordInterfaceTest import readExcel, getURL
from FlychordInterfaceTest.common import configHttp

# 获取接口文档第一页数据
excel = readExcel.Excel('DATA.xlsx', 0).read()


class test01(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_01(self):
        """查看琴行详情"""
        self.checkResult(excel[0][4], excel[0][6], excel[0][9])

    def checkResult(self, method, interface, data, headers=None):
        url = getURL.get_url(interface)
        print(url)
        info = configHttp.run_main(method, url, data, headers)
        print(info)
        self.assertEqual(int(info['code']), 404)


if __name__ == '__main__':
    unittest.main(verbosity=1)

等级+1版:

import unittest  # 导包
import ddt
from FlychordInterfaceTest import readExcel, getURL
from FlychordInterfaceTest.common import configHttp

# 获取接口文档第一页数据
excel = readExcel.element_list(readExcel.Excel('DATA.xlsx', 0).read())


@ddt.ddt
class test02(unittest.TestCase):
    @classmethod
    def setUpClass(cls):  # 所有用例运行之前执行一次
        pass

    @classmethod
    def tearDownClass(cls):  # 所有用例运行之后执行一次
        pass

    @ddt.data(*excel)
    @ddt.unpack
    def test_02(self, title, method, path, request, response):
        self._testMethodDoc = title  # 动态的用例描述
        self._testMethodName = title
        info = self.checkResult(method, path, request)
        self.assertEqual(response['success'], info['success'])

    def checkResult(self, method, interface, data, headers=None):
        url = getURL.get_url(interface)
        try:
            info = configHttp.run_main(method, url, data, headers)
            return info
        except:
            return '接口请求出错'


if __name__ == '__main__':
    unittest.main(verbosity=1)
  • ddt.ddt:装饰类,也就是继承TestCase的类。

  • ddt.data:装饰测试方法,参数是一系列的值。

  • ddt.file_data:装饰测试方法,参数是文件名。文件可以是json或者yaml类型。

    注意,如果文件是以“.yml”或者".yaml"结尾,ddt会作为yaml类型处理,其他文件都会作为json文件处理。

    如果文件是列表,列表的值会作为测试用例参数,同时,会作为测试用例方法名后缀显示。

    如果文件是字典,字典的key会作为测试用例方法的后缀显示,字典的value会作为测试用例参数。

  • ddt.unpack:传递的是复杂的数据结构时使用,比如使用列表或者元组,添加unpack后,ddt会自动把元组或者列表对应到多个参数上。
    @data(a,b)
      那么a和b各运行一次用例

    @data([a,d],[c,d])
      如果没有unpack,那么[a,b]当成一个参数传入用例运行
      如果有unpack,那么[a,b]被分解开,按照用例中的两个参数传递

8.创建run.py文件

脚本执行入口

import unittest
from time import strftime
# from logs.logs import DelAllLog
# from smtp.SendMail import sendMail
from BeautifulReport import BeautifulReport

# 删除所有旧日志
# DelAllLog()
# 格式化获取时间 以时间戳命名时不能用冒号(:)
ctime = strftime('%Y-%m-%d %H-%M-%S')
report_name = ctime + '-report.html'
test_suite = unittest.defaultTestLoader.discover('./case', pattern='test*.py')
# 调用测试报告框架
runner = BeautifulReport(test_suite)
# 定义测试报告相关的参数
runner.report(filename=report_name, description='琴行端自动化测试报告', log_path='./report')
# 发送邮件
# sendMail()

# 程序的执行入口
if __name__ == "__main__":
    unittest.main()

你可能感兴趣的:(python接口自动化学习(一))