python+requests+unittest接口自动化测试框架

                                python+requests+unittest接口自动化测试框架[之前写的文章,写在博客上,记录下来。]

前言:

       接口测试之前用的工具是postman和Jmeter,一般测试工具做接口测试的流程:选择接口测试工具—>配置接口请求和接口参数->参数化->进行测试,检查测试结果。

        这次打算用python+requests+unittest来设计接口测试框架,参考以上测试流程,还需要代码做到业务和数据的分离,这样使用起来比较灵活,以下记录过程。

开发环境:

  1. 操作系统:window7/window10
  2. 开发工具:IDEA+Pycharm
  3. Python版本:3.6 [python3.6.0]

、框架设计

2.1用到的模块

request:用于发送get,post,put等请求

xlrd:操作Excel,提取测试数据

logging:日志记录

json:数据json处理

configparser:读取配置文件

2.2框架结构

序号

目录

文件

1

common目录:存放一些公共的方法

公共方法:common.py

 

config目录:config配置文件以及数据库的相关信息,接口的相关信息等

日志服务:log.py

3

Data目录: 测试用例的测试数据

读取数据:read_excel.py

4

testcase目录:用于存放具体的测试case

Api接口:testApi.py

读取配置文件:readconfig.py

2

config目录:config配置文件以及数据库的相关信息,接口的相关信息等

配置文件:config.conf

3

Data目录: 测试用例的测试数据

数据文件:data.xlsx

4

testcase目录:用于存放具体的测试case

testLoginApi.py

5

run_main主执行程序

run_main.py

6

logs目录:执行生成的日志

"执行时才会生成日志目录"

7

repoort目录:存放每次执行过程中的测试结果

"执行时才会生成report目录"

2.3测试数据表:data.xlsx

数据包括:Name,url,Data,Method,Code

执行流程:

1、Excel定义URL,Data等列。脚本执行流程如下:

2、使用xlrd工具读取Excel中的信息和配置文件config.conf的初始url,拼接成一个个完整的请求。[或者这里直接用excel读取url也是可以的]

3、接口请求类拿到一个个完整的请求的去执行,这个过程需要记录日志,每一次执行情况都要进行记录,做到有迹可循。

4、使用unittest+htmlTestRunner执行,生成html报告。

2.4读取数据

数据是放在Excel中的,用xlrd来读取数据,写数据需要用到xluntils,

需要先安装:

pip install xlrd

pip install xluntils

思路

1使用xlrd方法读取xlsx的文件,然后存入list变量参数中

2执行时调用list变量参数

解决方案:

  1. 引用xlrd,获取xlsx的sheet,一列一列的读取,放入列表list中

For语句循环行读取每一列的值

方法:self.getRows()

      self.getSheet().cell_value(i, 0)

for i in range(1,self.getRows()):

       TestName.append(self.getSheet().cell_value(i, 0))

 

2.5打印日志

思路使用代码生成日志文件

解决方案:

1使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数

# logging对象,设置从那个等级开始提示

    logger = logging.getLogger()

#创建handler

    time_handler=logging.handlers.TimedRotatingFileHandler(logfile,'D')

    #handler设置日志格式

    fmt=logging.Formatter("%(asctime)s - %(name)s -%(module)s- %(levelname)s - %(message)s","%Y-%m-%d %H:%M:%S")    

    time_handler.setFormatter(fmt)

    #添加刚设置的handler

    logger.addHandler(time_handler)

2生成日志文件,文件:logs\当前日期\log+时间.log

    #日志文件

    logfile = os.path.join(log_path,"log%s.log") %time

 

2.6接口请求类封装

首先安装第三方模块requests

pip install requests

思路接口测试的封装(requests api请求)

if (method == "get" or "GET"):

            try:

                result = requests.get(url, params=data,cookies=cookies)

            except Exception as e:

                logging.error("发起get请求报错,错误是:", e)

                print("发起get请求报错,错误是:", e)

        elif (method == "post" or "POST"):

            try:

                result = requests.post(url, params=data,cookies=cookies)

            except Exception as e:

                logging.error("发起post请求报错,错误是:", e)

  

2.7业务接口测试testcase

login的接口测试用例

import sys, os

 

sys.path.append('../')

from common.read_excel import readData

from common.testApi import testApi

from common.readConfig import readConfig

 

import unittest

import json

import logging

 

# 生成日志文件(本程序单独执行时可使用)

# import common.log as log

# log.logfile()

 

class testLoginApi(unittest.TestCase):

    def setUp(self):

        print('\n')

 

    def test_LoginApi(self):

        # 测试login的接口

        logging.info('------testLoginApi------.')

 

         # 获取当前执行(调用)程序的当前目录,本程序执行,当前目录为D:\python_apitest\src\testcase;runtest.py执行时当前目录为:D:\python_apitest\src

        root_dir = os.path.abspath('.')

        if "testcase" in root_dir:

            data_path = "../data/data.xlsx"

            configpath="../config/config.conf"

        else:

            data_path = "data/data.xlsx"

            configpath="config/config.conf"

 

        # 获取参数化数据

        excel = readData(r'%s' % data_path)

        # excel = readData(r'D:\python_test\mdp_test3\config\data.xlsx')

        row = excel.getRows()

        url = excel.getUrl()

        method = excel.getMethod()

        headers = excel.getHeaders()

        data = excel.getData()

        exceptcode = excel.getCode()  # 参数data里的预期结果

 

        #读取配置文件

        #readconfig=readConfig("../config/config.conf")  #在当前程序调用时,使用这个

        readconfig=readConfig(configpath)

        #print (readconfig)

        baseurl=readconfig.get_http("baseurl")

        port=readconfig.get_http("port")

        #print (baseurl,port)

 

        # 一行一行参数化数据执行

        for i in range(0, row - 1):

 

            if port=="":

                requesturl=baseurl+url[i]

            else:

                requesturl=baseurl+":"+port+url[i]

            print (requesturl)

            try:

                api = testApi()

                result = api.requestsApid(method[i],requesturl,eval(data[i]))  # 调用requestApid的接口

                print("请求url%s" % result.url)  # 打印请求的url

                logging.info("请求url:%s" % result.url)

                apijson = result.json()  # 获取请求返回实际结果的json串值

                # print (apijson)

                # print (type(apijson))

                logging.info("请求返回值的json串值:%s" % apijson)

 

                # 获取返回实际结果json串值的state值

                actualstate = apijson["state"]

                actualmessage = apijson["message"]

            except Exception as e:

                print(e)

                logging.error(e)

            # print (actualcode)

            # print (eval(exceptcode[i]))

            # print (type(eval(exceptcode[i])))

            exceptstate = eval(exceptcode[i])["state"]

            exceptmessage = eval(exceptcode[i])["message"]

            # print (actualstate,type(actualstate))

            # print (exceptstate,type(exceptstate))

 

            if (actualstate == exceptstate):

                logging.info('检查结果:testLoginApi True,-实际state:%s,预期state:%s.' % (actualstate, exceptstate))

                print('检查结果:testLoginApi True,-实际state:%s,预期state:%s.' % (actualstate, exceptstate))

            else:

                logging.error('检查结果:testLoginApi False,-[实际state:%s,实际message:%s] ,[预期state:%s,预期message:%s].' % (

                actualstate, actualmessage, exceptstate, exceptmessage))

                print('检查结果:testLoginApi False,-[实际state:%s,实际message:%s] ,[预期state:%s,预期message:%s].' % (

                actualstate, actualmessage, exceptstate, exceptmessage))

            self.assertEqual(actualstate, exceptstate, "两者的值不相等")

 

    def tearDown(self):

        pass

 

     prin

2.8程序调用

例子1:run_main1.py

使用unittest.defaultTestLoader.discover方法执行测试用例

def runAutomation():

    filename = path + r'\report\Report_' + getNowTime() + '.html'

    fp = open(filename, 'wb')

    runner = HTMLTestRunner(

        stream=fp,

        title=u'接口自动化测试报告',

        description=u'接口自动化测试报告详细的信息'

    )

    runner.run(suite())

if __name__ == '__main__':

    runAutomation()

发布了112 篇原创文章 · 获赞 6 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/fen_fen/article/details/105360573