python接口自动化测试框架

1.接口测试框架的价值

1.效率
实现对所有测试脚本、测试数据文件以及测试报告文件的管理,提升接口测试执行和回归的效率
2.成本
降低人工的工作成本,可以通过框架自动来自动运行,提高人工的产能
3.复用
框架可以应对多种不同的接口测试工作的需求,适用性和扩展性强
4.规范
对接口测试成功物进行规范化管理,方便随时进行工作的开展以及成果物的查阅

2.框架设计思路

框架设计目标:最终只需要调整框架配置文件的一些参数,不需要人工干预测试脚本的执行
框架设计的过程
1.框架的层次确定下来:

1.配置层:框架的配置文件---csv
2.脚本层:独立接口脚本,联调的接口脚本
3.数据层:独立接口数据,联调接口数据
4.报告层:联调接口测试报告,框架测试报告(此次框架执行过程中,运行了哪些接口测试脚本?)

2.对框架的设计进行评审
3.创建框架对应的文件夹(框架分层):
框架分层

4.把现有相关的成果物,放入对应的文件夹,命名尽量有一个统一的规范:

脚本成果物(独立接口测试脚本,联调接口测试脚本)
测试数据文件
测试报告文件
框架配置文件

5.框架的设计
6.框架的实现
7.框架的调试运行

测试框架执行原理
测试框架执行原理
Unittest测试框架设计原理
Unittest框架设计原理

3.unittest框架使用原理及语法规则

案例演示V1.0(简单的框架脚本封装实现):通过unittest框架实现注册接口测试

2.设计:定义测试类,必须继承unittest类

class 测试类名(unittest.TestCase):

语法步骤
1.导入unittest库

import	unittest

2.定义测试类,必须继承unittest.TestCase

class RegisterTest(unittest.TestCase):

3.测试方法名字必须以test_开头

def test_register(self):

4.在main函数中直接使用unittest.main()即可

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

5.加入断言:assert断言函数,响应结果是json格式需进行类型转换

self.assertIn("用户名已经存在", str(response))

6.通过使用setUp进行测试的初始化工作,如果多个测试方法用的都是同一套数据的话,就可以在一个setUp里写

def setUp(self):
   self.url ="http:/xxxxxxxxxxx/user/register.do"
    self.userinfo = {"username": "程勇1",
                     "password": "123456",
                     "email": "chengyong1@abcd.com",
                     "phone": "13825465786",
                     "question": "最喜欢的书",
                     "answer": "幸福人生"}

完整代码演示

# 定义测试类,继承unittest框架
import unittest

import requests


class RegisterTest(unittest.TestCase):
    # 使用setUp方法完成接口测试的初始化工作
    def setUp(self):
        self.url = "http:/xxxxxxxxxxx/user/register.do"
        self.userinfo = {"username": "程勇1",
                         "password": "123456",
                         "email": "chengyong1@abcd.com",
                         "phone": "13825465786",
                         "question": "最喜欢的书",
                         "answer": "幸福人生"}
    # 定义unittest测试方法
    def test_register(self):

        # 发送接口请求
        s = requests.session()
        response = s.post(self.url, self.userinfo).json()
        print(response)
        # 把json格式的响应结果转换成字符串
        # result = str(response)
        # msg = result.find("用户名已经存在")
        # if msg > 0:
        #     print("注册接口测试通过")
        # else:
        #     print("注册接口测试失败")
        # 现在使用unittest框架断言来进行结果判断
        self.assertIn("用户名已经存在", str(response))


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

案例演示V1.2(简单的框架脚本封装实现):通过unittest框架实现检查用户名或邮件是否有效接口测试

7.通过使用teardown进行测试的回收工作(setUp打开文件,teardown关闭文件)
完整代码演示:

# coding:utf8
# 实验二:针对检查接口通过unittest框架进行脚本实现
# 导入相关库文件
# 定义测试类,继承unittest框架
import csv
import unittest

import requests


class checktest(unittest.TestCase):
    # 使用setUp进行接口测试初始化
    def setUp(self):
        self.file1 = open("../testdatafile/ind_interface/check_test_data.csv", "r")
        self.file2 = open("../testresultfile/ind_interface/check_result.csv", "w")
        self.url = "http://xxxxxxxxxx/user/check_vaild.do"
    # 定义接口测试方法
    def test_check(self):
        # 从csv文件中读取测试数据
        checkinfo = {}

        table = csv.reader(self.file1)
        for row in table:
            checkinfo["str"] = row[0]
            checkinfo["type"] = row[1]
            print(row[0])
            s = requests.session()
            response = s.post(self.url, data=checkinfo).text
            print(response)
            # 原来是用if判断添加断言,现在用assert添加断言
            self.assertIn(row[2], str(response))

    # 通过teardown方法进行回收工作
    def tearDown(self):
        self.file1.close()
        self.file2.close()


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

案例演示V1.3(多个接口联调测试):通过unittest框架实现多个接口的联调测试------注册接口,登录接口

实现步骤
1.导入unittest框架
2.定义测试类-----指定一个测试类实现多个测试方法
3.定义setUp进行初始化
4.定义test方法
5.使用测试套进行测试用例的执行
6.使用文件加载的方式进行测试用例的执行

思考:框架如何进行测试方法执行顺序控制?
1.如果框架中只有一个方法:先执行setUp,然后再执行测试方法test_xxx,最后才执行tearDown
2.如果框架中有多个方法:是按照asc码顺序执行的(方法名字母顺序a–z),执行顺序如下:

setUp
测试方法test_case1
tearDown
setUp
测试方法test_case2
tearDown
....

使用测试套进行测试用例的执行步骤
1.在main里面声明测试套对象

suite = unittest.TestSuite()

2.把需要执行的测试用例用addTest方法加入测试套中
由addTest的顺序来进行测试方法执行顺序的控制

suite.addTest(测试类的名称("test_xxx"))

3.声明框架运行的对象

runner = unittest.TextTestRunner()

4.通过runner对象执行测试套件

runner.run(suite)
if __name__ == '__main__':
    # 声明测试套对象
    suite = unittest.TestSuite()
    # 调用addTest方法调用类里面的方法就把类写再前面,再写入方法名
    suite.addTest(mulinterfacetest("test_case2"))
    suite.addTest(mulinterfacetest("test_case1"))
    # 声明测试运行对象
    runner = unittest.TextTestRunner()
    runner.run(suite)

测试框架之unittest.main()运行原理
在main里面执行测试方法无法控制执行顺序,所有的用例方法只要没有注释都是会全部执行

if __name__ 'main':
unittest.main()

在这里插入图片描述

测试框架之unittest.TestSuite()运行原理
如果想指定执行某一个测试用例就用TestSuite测试套来执行
在这里插入图片描述

使用文件加载的方式进行测试用例的执行
执行一些或一个python的测试文件

实现步骤:
1.声明文件路径
2.通过调用unittest对应的discower方法打开对应的测试文件
3.声明一个runner的对象
4.执行指定的测试文件

# 以文件的方式来进行测试框架的执行
    # 声明文件所在路径
    testdir = './'  # 这里是路径
    discower = unittest.defaultTestLoader.discover(testdir, pattern="test*.py")
    # 声明测试运行对象
    runner = unittest.TextTestRunner()
    runner.run(discower)

小结:
unittest框架的使用要求:
1.导入

import  unittest

2.定义测试类需要继承unittest

class 测试类名(unittest.TestCase)

unittest测试框架的基本组成要素
1.setUp初始化方法-------这个方法是可选的,可以有也可以没有,这个是测试前期的初始化工作
2.以test_打头的测试方法
3.tearDown方法资源回收------可选,一般用来关闭一些对象释放对象或者关闭一些文件
4.运行方式
unitest框架的执行顺序:
setUp进行初始化
执行测试方法
tearDown进行资源回收
三种不同的框架运行方式的对比:
unittest.main()好处: 特点:只能执行当前类中对应的所有测试方法
1.依次执行当前文件中对应测试类的所有测试方法
2.执行顺序以asc码顺序
3.一般的测试方法名称建议定义为:test_case1,test_case2…

测试套件的执行: 特点:按照加载顺序的顺序和个数进行执行
注意:运行模式要改为以python文件而不是测试框架模式运行
在这里插入图片描述

1.声明一个测试套

	suite = unittest.TestSuite()

2.通过addTest方法添加测试用例------对应的测试方法

suite.addTest(类名("测试方法名"))

3.声明一个测试运行对象

runner  = unittest.TextTestRunner()

4.执行测试套

runner.run(suite)

测试文件执行: 特点:执行任意指定路径下的任意相关命名的python测试脚本,执行每一个文件中所有的测试方法,顺序也是按照asc码顺序进行
1.声明文件所在路径
2.定义discower对象打开相关的脚本文件

discower = unittest.defaultTestloder.discower(文件路径,pattern=“test_*.py”)

3.声明测试运行对象

runner = unittest.TexttestRunner()

4.执行测试套

runner.run(discower)

3.自主研发测试框架

需求原型
1.框架目录结构,一般的设计思路:配置层,脚本层,报告层,驱动层;这里的分层没有加入驱动层

框架分层

2.框架各层需要完成的工作:
1.配置层:config,不同人设计的配置层相关内容是不一样的,这里设计的配置层里面的放的是csv文件,由配置文件来控制此次测试执行需要调用哪些测试脚本

2.脚本层:script, ind_interface:存放独立接口测试脚本,表示一个类中有一个测试方法,完成一个接口的测试;mul_interface:存放联调接口测试脚本,一个类中有多个测试方法,完成接口与联调的测试
注意:脚本文件的名称要有一定的规范性,此次规定测试脚本文件以test_开头

3.测试数据文件层:testdatafile,ind_interface:存放独立接口测试脚本对应的测试数据文件;mul_interface:存放的是联调接口测试脚本对应的测试数据文件

4.测试报告文件层:testresultfile,framresult:测试框架报告;ind_interface:存放独立接口测试报告;mul_interface:存放联调接口测试报告

5.框架驱动层:test_driver:存放测试框架的驱动程序

框架的测试执行过程:
先由框架驱动层中的框架驱动程序运行,依据配置层相关的设置调用对应的脚本层的程序进行执行,相关的脚本运行时,如果需要测试数据,则在数据层进行脚本文件的读取,测试脚本执行结束后,会写明相关的测试报告文件,并存入测试报告层

测试框架前期的准备工作:
1.依据框架需求搭建框架项目及模块
2.接口测试数据文件向框架转移

框架分层目录结构图:这里加入驱动层
在这里插入图片描述

框架测试脚本的研发:
1.重构测试脚本:案例演示:更新用户信息接口测试
实现步骤:
1.在框架对应的分层下创建新的python文件(注意:符合命名规范)
2.按照unittest框架的思想进行脚本设计

一般来讲不需要这么多版本同时存在,看实际需求,如果1.0够用就直接可以测试执行了,若感觉1.0不充分就注释掉或者是分成不同得测试方法,还是在一个文件里写;这里采用的是用不同的测试方法实现不同版本的测试
V1.0
1.导入unittest
2.定义一个类,继承unittest
3.传入固定的接口测试数据(一组)
4.assert进行判断
V2.0
4.是否需要测试数据文件
V3.0
5.加入测试报告文件

3.测试脚本的实现:V1.0

脚本演示

# coding:utf8
#*********************************************************************
# 对更新用户信息的接口进行测试,使用unittest框架技术
# 接口说明
# 接口访问地址:
    # http://xxxxxxx/update_infomation.do
# 接口传入参数:
    # 1.email  2.phone 3.question 4.answer
# 接口预期返回值
    # 1.email已存在,请更换email再尝试更新 2.更新个人信息成功 3.更新个人信息失败"
#************************************************************************
# 脚本实现:
# 导入相关的库
# 定义测试类,继承unittest框架
import unittest
import requests

class updateuser_test(unittest.TestCase):
    # V1.0版本,传入一组固定的接口测试数据,进行接口测试
    def test_case1(self):
        # 传入指定的接口测试数据
        url = "http://xxxxxxx/user/update_information.do"
        userinfo = {"email": "xiugaiyonghu@qq.com",
                    "phone": "13898768578",
                    "question": "最喜欢的书",
                    "answer": "十万个为什么"}
        # 进行接口调用
        response = requests.post(url, data=userinfo).text
        print(response)


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

运行结果

Ran 1 test in 0.032s

OK
{"status":1,"msg":"用户未登录"}

设计问题分析:测试更新用户的接口,需要先进行登录
测试场景1:未登录,进行更新,提示:用户未登录
测试场景2:先登录,再进行更新(遇到问题:发送了登录请求,在调用更新接口时还是提示“用户未登录“需要传入sessionID)

需要解决的问题:解决方案:
方案1(常用):在当前的测试类中,追加一个setUp方法,登录的测试脚本写入setUp方法中
方案2:在当前的测试类中,追加一个新得测试方法test_case1(完成登录的调用),把原来的更新测试方法名改为test_case2
方案3:在当前的测试类及测试方法中,前面追加一段代码,完成登录的调用
方案四:另外创建一个脚本文件,来实现登录,通过测试框架进行接口测试联调

脚本传入sessionID的解决办法:
先用接口测试工具看一下接口响应里的JSESSION字典,在登录测试方法里获取到,并转换成字典,再写上字典的key,作为更新用户的传参使用
V1.0完整脚本案例

# coding:gbk
#*********************************************************************
# 对更新用户信息的接口进行测试,使用unittest框架技术
# 接口说明
# 接口访问地址:
    # http://localhost:8888/jwshoplogin/user/update_infomation.do
# 接口传入参数:
    # 1.email  2.phone 3.question 4.answer
# 接口预期返回值
    # 1.email已存在,请更换email再尝试更新 2.更新个人信息成功 3.更新个人信息失败"
#************************************************************************
# 脚本实现:
# 导入相关的库
# 定义测试类,继承unittest框架
import unittest
import requests

class updateuser_test(unittest.TestCase):
    # 通过setUp方法实现登录接口的调用
    def setUp(self):
        url = "http://xxxxxxx/user/login.do"
        userinfo = {"username": "张三1",
                    "password": "123456"}
        response = requests.post(url, data=userinfo)
        # print(response.text)
        # 获取sessionID转成字典类型写上字典类型的key,并存入一个变量,作为更新用户的的传参
        self.sessionID = dict(response.cookies)['JSESSIONID']
        print(self.sessionID)
    # V1.0版本,传入一组固定的接口测试数据,进行接口测试
    def test_case2(self):
        # 传入指定的接口测试数据
        url = "http://xxxxxxx/user/update_information.do"
        userinfo = {"email": "xiugaiyonghu@qq.com",
                    "phone": "132546677685",
                    "question": "最喜欢的书",
                    "answer": "西游记"}
        # 获取登录的sessionID并传入请求方法中
        session = {'JSESSIONID': self.sessionID}
        print(session)
        # 进行接口调用
        response = requests.post(url, data=userinfo, cookies=session).text
        print(response)
        self.assertIn("更新个人信息成功", response)


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

运行结果

98D0C3CCB24BA805139F3CE4802C9C02
{'JSESSIONID': '98D0C3CCB24BA805139F3CE4802C9C02'}
{"status":0,"msg":"更新个人信息成功","data":{"id":38,"

测试脚本实现:V2.0
1.是否需要测试数据文件:对测试数据文件进行设计(测试用例的设计)
更新用户数据接口,测试数据分析:

1.1正常:四组数据:1.email,2.phone,3.answer,3.question;考虑只更新任意一个数据,还是更新多组数据,或是更新全部数据都可以
1.2异常:考虑:1.未登录,2.邮箱冲突,3.电话的长度不正确,4.问题为空,5.答案为空等等

测试数据文件
在这里插入图片描述

2.把测试数据文件中的内容传入脚本

案例代码演示

# v2.通过csv文件进行更新测试数据的读取
# python文件名update_v2_test.py
#*********************************************************************
# 对更新用户信息的接口进行测试,使用unittest框架技术
# 接口说明
# 接口访问地址:
    # http://localhost:8888/jwshoplogin/user/update_infomation.do
# 接口传入参数:
    # 1.email  2.phone 3.question 4.answer
# 接口预期返回值
    # 1.email已存在,请更换email再尝试更新 2.更新个人信息成功 3.更新个人信息失败"
#************************************************************************
import csv
import os
import unittest

import requests


class Update_v2_test(unittest.TestCase):
    # 通过setUp方法实现登录接口的调用
    def setUp(self):
        # 从测试数据文件中读取url和登录测试数据
        path = os.getcwd()
        # print(path)
        # p1 = os.path.abspath(os.path.dirname(path)+os.path.sep+".")
        # print(p1)
        # 获取当前路径的上两级目录路径
        p2 = os.path.abspath(os.path.dirname(path)+os.path.sep+"..")
        # print(p2)
        # 获取到的上两级目录路径加上csv测试数据所在路径
        self.fpath = p2 + "\\test_data_file\\ind_interface\\updateuser_test_data.csv"
        # print(fpath)
        # self.file = open("../../test_data_file/ind_interface/updateuser_test_data.csv")
        userinfo = {}
        file1 = open(self.fpath, "r")
        table = csv.reader(file1)
        for row in table:
            url = row[0]
            userinfo[row[3]] = row[4]
            userinfo[row[5]] = row[6]
            print(userinfo)
            # 只想打印第一行信息就用break退出循环
            break
        response = requests.post(url, data=userinfo)
        self.sessionID = dict(response.cookies)["JSESSIONID"]
        print(self.sessionID)

    # V2.0版本,读取指定测试数据文件中对应的内容,进行接口测试
    def test_case2(self):
        # 打开对应的文件
        file1 = open(self.fpath, "r")
        # 如何从指定行开始进行读取
        table = csv.reader(file1)
        userinfo = {}
        number = 0
        for row in table:
            number += 1
            if number > 1:
                url = row[0]
                expresult = row[1]
                j = int(row[2])
                # 下标从2开始,j表示有几组数据的下标乘以两组数据加上初始值,最后的2表示步长
                for i in range(3, j*2+2, 2):
                    userinfo[row[i]] = row[i+1]
                print(userinfo)

                # 获取登录的sessionID并传入请求方法中
                session = {'JSESSIONID': self.sessionID}
                print(session)
                # 进行接口调用
                response = requests.post(url, data=userinfo, cookies=session).text
                print(response)
                userinfo = {}
                self.assertIn("更新个人信息成功", response)


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

小结:
注意的事项:
1.文件位置的读取,获取当前路径首先导包import os,然后写path = os.getcwd()获取上一级路径p1 = os.path.abspath(os.path.dirname(path)+os.path.sep+"."),获取前两级路径在这里插入代码片p2 = os.path.abspath(os.path.dirname(path)+os.path.sep+"..")获取上一级后面写一个点,获取上两级写两个点
2.数据文件的设计:把固定的内容放在前面的列,把不定向的参数放在后面的列中,通过手工加入参数个数,方便进行循环读取,注意参数的正确性,先设计正确的数据,保证脚本测试通过,再设计错误的数据。
3.从指定的某一行开始读取内容number =0 for row in table:追加number += 1例如想从第四行读起,前三行都空转过去if num >4

num = 0
for row in table:
	num += 1
	if num > 4:

测试脚本实现3.0:
加入测试报告文件:生成HTML格式的测试报告
步骤:
1.下载HTMLTestRunner.py

下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

2.拷贝到项目文件夹下
3.导入HTMLReport包

from HTNLTestRunner import HTMLTestRunner

4.生成测试报告的脚本

做好测试执行前的准备工作,指定要执行的测试用例
1.以wb(二进制写文件)模式打开测试报告文件
2.使用HTMLTestRunner方法创建HTML文件
3.执行测试
4.关闭文件

代码演示

# V3.0 创建HTML格式的测试报告文件
# python文件名updateuser_v3_test.py
#*********************************************************************
# 对更新用户信息的接口进行测试,使用unittest框架技术
# 接口说明
# 接口访问地址:
    # http://localhost:8888/jwshoplogin/user/update_infomation.do
# 接口传入参数:
    # 1.email  2.phone 3.question 4.answer
# 接口预期返回值
    # 1.email已存在,请更换email再尝试更新 2.更新个人信息成功 3.更新个人信息失败"
#************************************************************************
import csv
import os
import unittest
import requests
from HTMLTestRunner import HTMLTestRunner

class Updateuser_v3_test(unittest.TestCase):
    # 通过setUp方法实现登录接口的调用
    def setUp(self):
        # 从csv测试数据文件中读取url和登录测试数据
        path = os.getcwd()
        # 获取当前路径的上两级路径
        p2 = os.path.abspath(os.path.dirname(path) + os.path.sep+"..")
        # 上两级路径加上测试数据所在路径
        self.fpath = p2 + "\\test_data_file\\ind_interface\\updateuser_test_data.csv"
        userinfo = {}
        file = open(self.fpath, "r")
        table = csv.reader(file)
        for row in table:
            url = row[0]
            userinfo[row[3]] = row[4]
            userinfo[row[5]] = row[6]
            print(userinfo)
            # 只打印第一行登录的测试数据,这里用break退出循环
            break
        response = requests.post(url, data=userinfo)
        # print(response)
        # 获取sessionID转换成字典类型,写上字典的key并存在变量里作作为写一个接口的调用
        self.sessionID = dict(response.cookies)["JSESSIONID"]
        # print(sessionID)

    def test_case(self):
        file = open(self.fpath, "r")
        table = csv.reader(file)
        userinfo = {}
        n = 0
        for row in table:
            if n > 0:
                url = row[0]
                # 各行数据组的和的下标
                j = int(row[2])
                # 下标从3开始,一组是两个数据乘以2加上开始的初始值,步长是2
                for i in range(3, j*2+3, 2):
                    # i是字典大的key,i+1是字典的值
                    userinfo[row[i]] = row[i + 1]
                # print(userinfo)
                # 传入上一个接口的sessionID
                session = {"JSESSIONID": self.sessionID}
                # print(session)
                response = requests.post(url, data=userinfo, cookies=session).text
                print(response)
            n += 1



if __name__ == '__main__':
    # unittest.main()
    path = os.getcwd()
    p2 = os.path.abspath(os.path.dirname(path) + os.path.sep + "..")
    # 加载测试套
    suite = unittest.TestSuite()
    suite.addTest(Updateuser_v3_test("test_case"))
    # 定义测试报告文件
    filename = p2 + r"\test_result_file\ind_interface\updateuser_test_report.html"
    # 以wb(二进制写文件的方式)打开文件
    file = open(filename, "wb")
    # 调用HTML测试报告的报告生成测试报告
    runner = HTMLTestRunner(stream=file, title="更新用户接口测试", description="接口测试报告")
    runner.run(suite)
    file.close()

运行结果
注意:这里测试脚本类文件里面写的测试套,运行的时候需要修改运行方式,给文件改个名字,要么再新建一个文件写main函数调用才可以执行测试套,要不然还是会再框架里面执行就不会生成测试报告

.<_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> 
Time Elapsed: 0:00:00.284698

生成的测试报告
在这里插入图片描述

小结:
1.在main函数中生成html格式的测试报告

1.获取要写入测试报告文件对应位置的路径
2.给定具体的测试报告文件名
3.以wb(二进制写入)的方式打开文件
4.设置测试套,并添加要测试的方法
5.生成测试报
runner = HTMLTestRunner(stream=file, title="标题", description="描述")
6.调用runner对象执行测试套
runner.run(suite)
7.关闭测试报告文件

测试框架设计流程图在这里插入图片描述

4.测试框架驱动程序设计

驱动程序流程图
设计及实现框架驱动程序
V1.0在配置文件中写入一个测试文件进行执行
1.设计一个配置文件:脚本名称,脚本所在路径
在这里插入图片描述

2.读取配置文件的内容
3.找到对应的脚本文件进行调用

# 测试框架驱动程序1.0版本,文件名runner_v1_test
# 只是从配置文件中读取一个脚本文件进行调用
import unittest
import csv

if __name__ == '__main__':
    # 指定对应得脚本路径1.0版本;从csv文件中读取相关的路径和文件名
    file = open(r"E:\workspace2\interfaceframe\config\config1.csv")
    table = csv.reader(file)
    num = 0
    for row in table:
        if num > 0:
            testdir = row[0]
            fname = row[1]
            print(testdir, fname)
        num += 1
    # testdir = "E:\workspace2\interfaceframe\script\ind_interface"
    discover = unittest.defaultTestLoader.discover(testdir, pattern=fname)
    # 定义一个运行对象
    runner = unittest.TextTestRunner()
    runner.run(discover)

运行结果

"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
{"status":0,"msg":"更新个人信息成功"}
.
----------------------------------------------------------------------
Ran 1 test in 0.411s

OK

小结:
思路:由简到繁选择一种框架调用模式defaultloader方式,先用常量值进行脚本的调试,路径和脚本名称都是常量,再把常量值改为变量值,逐个替换不要全部替换,再把变量值改为从文件读取

发现问题,添加print语句进行分析;问题:路径不一致,级别关系发生了变化;解决问题,调整脚本中对应的路径级别

discover = unittest.defaultTestLoader.discover(路劲, pattern=脚本名称)

V2.0在配置文件中写入两个测试文件进行执行:
1.修改配置文件
2.进行脚本的修改

# 测试框架驱动程序1.0版本,文件名runner_v1_test
# 只是从配置文件中读取一个脚本文件进行调用
import unittest
import csv

if __name__ == '__main__':
    # 指定对应得脚本路径1.0版本;从csv文件中读取相关的路径和文件名
    file = open(r"E:\workspace2\interfaceframe\config\config1.csv")
    table = csv.reader(file)
    num = 0
    for row in table:
        if num > 0:
            testdir = row[0]
            fname = row[1]
            print(testdir, fname)
            # testdir = "E:\workspace2\interfaceframe\script\ind_interface"
            discover = unittest.defaultTestLoader.discover(testdir, pattern=fname)
            # 定义一个运行对象
            runner = unittest.TextTestRunner()
            runner.run(discover)
        num += 1

运行结果

{'username': '李慧1', 'password': '123456'}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data"}
{"status":0,"msg":"更新个人信息成功","data":}
{'username': '李慧1', 'password': '123456'}
.
----------------------------------------------------------------------
Ran 1 test in 0.390s

OK
{'email': 'lihuixiugai1@qq.com'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'phone': '13277777777'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'question': '李慧1问题更新'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'answer': '李慧1答案更新'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'email': 'lihuixiugai2@qq.com', 'phone': '13277777776'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'question': '李慧2问题更新', 'answer': '李慧2答案更新'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
{"status":0,"msg":"更新个人信息成功","data"}
{'email': 'lihuixiugai3@qq.com', 'phone': '13277777778', 'question': '李慧3问题更新', 'answer': '李慧3答案更新'}
{'JSESSIONID': '9D27D9C5104EEECEF6D94D07DD7C2A57'}
.
----------------------------------------------------------------------
Ran 1 test in 0.416s

OK

V3.0在配置文件中针对不同的运行状态进行文件的执行:
1.升级改造配置文件---------加入一列状态列(状态表示0/1;RUN/ONRUN;NO/YES:运行和不运行)
在这里插入图片描述
2.脚本的调整--------加入条件判断

# 测试框架驱动程序1.0版本,文件名runner_v1_test
# 只是从配置文件中读取一个脚本文件进行调用
import unittest
import csv

if __name__ == '__main__':
    # 指定对应得脚本路径1.0版本;从csv文件中读取相关的路径和文件名
    file = open(r"E:\workspace2\interfaceframe\config\config1.csv")
    table = csv.reader(file)
    num = 0
    for row in table:
        if num > 0 and row[2] == "yes":
            testdir = row[0]
            fname = row[1]
            print(testdir, fname)
            # testdir = "E:\workspace2\interfaceframe\script\ind_interface"
            discover = unittest.defaultTestLoader.discover(testdir, pattern=fname)
            # 定义一个运行对象
            runner = unittest.TextTestRunner()
            runner.run(discover)
        num += 1

运行结果

E:\workspace2\interfaceframe\script\ind_interface updateuser_v2_test.py
E:\workspace2\interfaceframe\test_data_file\ind_interface\updateuser_test_data.csv
{'username': '李慧1', 'password': '123456'}
{'email': 'lihuixiugai1@qq.com'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data"}
{'phone': '13277777777'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data":{"id":47,"username":"李慧1}
{'question': '李慧1问题更新'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data"}
{'answer': '李慧1答案更新'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data":{"id":47,"username":"李慧1}
{'email': 'lihuixiugai2@qq.com', 'phone': '13277777776'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data":{"id":47,"username":"李慧1}
{'question': '李慧2问题更新', 'answer': '李慧2答案更新'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
{"status":0,"msg":"更新个人信息成功","data"}
{'email': 'lihuixiugai3@qq.com', 'phone': '13277777778', 'question': '李慧3问题更新', 'answer': '李慧3答案更新'}
{'JSESSIONID': 'A7284724F342B08EE928506687CB14A2'}
.
----------------------------------------------------------------------
Ran 1 test in 0.274s

OK

V4.0按照测试人员指定的顺序来执行相应的测试文件:
1.升级改造配置文件-----------加入执行顺序列
在这里插入图片描述
2.修改脚本

# v4.0完成从配置文件中读取测试脚本,执行状态以及执行顺序
# 文件名称 runner_v2_test
# 实验:对数据字典的内容进行排序
import operator
# dic = {"testA": 3, "testC": 1, "testB": 4, "testD": 2}
# dicn = sorted(dic.items(), key=operator.itemgetter(1))
# print(dicn)
# for fn in dicn:
#     print(fn[1])

# 实验:把配置文件中的内容放入字典中
# import csv
# 以只读方式打开
# file = open(r"E:\workspace2\interfaceframe\config\config1.csv")
# tanle = csv.reader(file)
# # line = len(open(r"E:\workspace2\interfaceframe\config\config1.csv").readlines())
# # print(line)
# dic = {}
# listd = []
# line = 0
# for row in tanle:
#     # print(row[0])
#     if line > 0:
#         dic = {}
#     # 把文件中读取的数据放入字典
#         dic[row[1]] = row[0]
#         dic["num"] = int(row[3])
#         # print(dic)
#     line += 1
#     if dic != {}:
#         listd.append(dic)
# print("n,行数", line)
# # print(listd)
# dicn = sorted(listd, key=operator.itemgetter("num"))
# print(dicn)
# for i in range(0, line-1):
#     n = 0
#     for content in dicn[i].items():
#         if n == 0:
#             fname = print(content[0])
#             fdir = print(content[1])
#             print(fname, fdir)
#         n += 1

#**********************V4.0驱动程序**************************************************
import unittest
import csv
import operator


if __name__ == '__main__':
    # 打开对应的配置文件,进行读取
    # 以只读方式打开
    file = open(r"E:\workspace2\interfaceframe\config\config1.csv")
    tanle = csv.reader(file)
    # line = len(open(r"E:\workspace2\interfaceframe\config\config1.csv").readlines())
    # print(line)
    dic = {}
    listd = []
    line = 0
    for row in tanle:
        # print(row[0])
        if line > 0:
            dic = {}
        # 把文件中读取的数据放入字典
            dic[row[1]] = row[0]
            dic["order"] = int(row[3])
            # print(dic)
        line += 1
        if dic != {}:
            listd.append(dic)
    print("n,行数", line)
    # print(listd)
    dicn = sorted(listd, key=operator.itemgetter("order"))
    print(dicn)
    for i in range(0, line-1):
        n = 0
        for content in dicn[i].items():
            if n == 0:
                fname = (content[0])
                fdir = (content[1])
                print(fname, fdir)
                # 调用脚本进行执行
                discover = unittest.defaultTestLoader.discover(fdir, pattern=fname)
                # 定义一个运行对象
                runner = unittest.TextTestRunner()
                runner.run(discover)
            n += 1

V5.0按照测试顺序和是否运行来确定要执行哪些测试:
复杂的程序编写思路:
1.分解任务
2.逐步合并,分段调试
3.脚本设计思路:

突破点:python提供的数据字典的排序:
	脚本名,脚本路路径、执行顺序,是相关的一组数据,不是无关的;import operator  sorted(数据字典,key=operater.itemgetter(下标或标签))
实验一:给定一些字典的基本数据,排序算法是否可行
dic = {"testA": 3, "testC": 1, "testB": 4, "testD": 2}
dicn = sorted(dic.items(), key=operator.itemgetter(1))
print(dicn) -----排序算是否可行
实验二:把csv配置文件的一行内容导入字典中
实验三:把csv配置文件的多行内容导入到字典中
实验四:检验读取的顺序是否正确,能否正确执行
实验五:加入对状态的判断
# coding:utf8
# 把所有配置文件中的内容全部进行读取
# 文件名:runner_v3_test
import unittest
import csv
import operator


if __name__ == '__main__':
    # 打开对应的配置文件,进行读取
    # 以只读方式打开
    file = open(r"E:\workspace2\interfaceframe\config\config1.csv", 'r')
    table = csv.reader(file)
    # line = len(open(r"E:\workspace2\interfaceframe\config\config1.csv").readlines())
    # print(line)
    dic = {}
    listd = []
    line = 0
    for row in table:
        # print(row[0])
        if line > 0:
            # 每一次执行之前清空字典
            dic = {}
        # 把文件中读取的数据放入字典
            dic[row[1]] = row[0]
            dic["order"] = int(row[3])
            # 把脚本的运行状态加入字典数据
            dic["stada"] = row[2]
            # print(dic)
        line += 1
        if dic != {}:
            listd.append(dic)
    print("n,行数", line)
    # print(listd)
    dicn = sorted(listd, key=operator.itemgetter("order"))
    # print(dicn)
    # 从列表字典读取数据,for key,value in dict.items()

    for i in range(0, line-1):
        n = 0
        for content in dicn[i].items():
            if n == 0:
                # print(content)
                fname = (content[0])
                fdir = (content[1])
                # print("文件名", fname, "路径", fdir)
            if n == 2:
                # print(content)
                state = content[1]
                print("state", state)
                if state == "yes":
                    # 调用脚本进行执行
                    print("最终运行的程序", fname)
                    discover = unittest.defaultTestLoader.discover(fdir, pattern=fname)
                    # 定义一个运行对象
                    runner = unittest.TextTestRunner()
                    runner.run(discover)

            n += 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值