美文网首页
unittest小结--多种方式

unittest小结--多种方式

作者: 我是孟小鱼呀 | 来源:发表于2019-12-03 14:29 被阅读0次

前提条件:数据已经存放在excel表格中,数据表名data.xlsx,表单名login_data
test_http_request.py(unittest)测试http_request.py

http_request.py
# -*-coding: utf8 -*-

import requests

class HttpRequest(object):

    def http_request(self, url, data, method, expected=None, cookie=None):
        if method.lower() == 'get':
            res = requests.get(url, data=None, cookies=cookie, verify=False)
        else:
            res = requests.post(url, data, cookies=cookie, verify=False)

        return res

一、test_http_request

(1)初始化参数方法,但要超继承
import unittest

#继承unittest中的类TestCase,用来编写用例
class TestHttpRequest(unittest.TestCase):
#保留继承unittest原来的方法,拓展需要的参数
#初始化函数
    def __init__(self, methodName, url, data, method, expected):#通过初始化函数传参
        super(TestHttpRequest, self).__init__(methodName)#保留父类的方法
        self.url = url
        self.data = data
        self.method = method
        self.expected = expected
    def setUp(self):
        pass
#测试用例参数化
    def test_api(self):
        res = HttpRequest().http_request(
            self.url,
            self.data,
            self.method,
            self.expected,
            getattr(GetData, 'Cookie')
        )
        if res.cookies:  # 如果cookie有的话,那就更新COOKIE
            setattr(GetData, 'Cookie', res.cookies)
        try:
            self.assertEqual(self.expected, res.json()['info'])
        except AssertionError as e:
            print('test_api的错误是:{}'.format(e))
            raise e
        print(res.json())
(2)ddt方式传数据
test_data = DoExcel('data_3.xlsx', 'login_data').get_data()
@ddt
class TestHttpRequest(unittest.TestCase):

    def setUp(self):
        pass
    @data(*test_data)
    def test_api(self, item):
        res = HttpRequest().http_request(
            item['url'],
            eval(item['data']),
            item['method'],
            item['expected'],
            getattr(GetData, 'Cookie')
        )
        if res.cookies:  # 如果cookie有的话,那就更新COOKIE
            setattr(GetData, 'Cookie', res.cookies)
        try:
            self.assertEqual(item['expected'], res.json()['info'])
        except AssertionError as e:
            print('test_api的错误是:{}'.format(e))
            raise e
        print(res.json())

二、test_suite控制测试用例执行

(1)取数据方法一:全都取出来
test_data = DoExcel1('data.xlsx', 'login_data').get_data()
suite = unittest.TestSuite()#加载用例到用例的方法名
for item in test_data:#从test_data中取数据
    suite.addTest(
        TestHttpRequest(
            'test_api',
            item['url'],
            eval(item['data']),#把字符串转换成原来的格式字典
            item['method'],
            item['expected']
        )
    )
(2)取数据方法二:用哪个取哪个
t = DoExcel2('data.xlsx', 'login_data')
suite = unittest.TestSuite()
for i in range(1, t.max_row + 1):
    suite.addTest(
        TestHttpRequest(
            'test_api',
            t.get_data(i, 1),
            eval(t.get_data(i, 2)),
            t.get_data(i, 3),
            t.get_data(i, 4)
        )
    )

注意:上述两种方法选择一种使用,不是同时使用,推荐使用第一种

执行用例
with open('test_login_report.html', 'w', encoding='utf8') as file:
    runner = HTMLTestRunner(
        output="./reports/",
        stream=file,
        verbosity=2,
        descriptions=True
    )
    runner.run(suite)

三、do_excel

do_excel读数据的目的是为了把返回的数据以列表嵌套字典的形式输出

(1)方法一:读出全部数据
# -*-coding: utf8 -*-
from openpyxl import load_workbook
class DoExcel1(object):

    def __init__(self, file_name, sheet_name):
        self.file_name = file_name
        self.sheet_name = sheet_name

    def get_data(self):
        wb = load_workbook(self.file_name)
        sheet = wb[self.sheet_name]
        max_row = sheet.max_row

        test_data = []
        for row in range(1, max_row + 1):
            sub_data = {}
            sub_data['url'] = sheet.cell(row, 1).value
            sub_data['data'] = sheet.cell(row, 2).value
            sub_data['expected'] = sheet.cell(row, 3).value
            sub_data['method'] = sheet.cell(row, 4).value
            test_data.append(sub_data)
        return test_data
    #def write_back(self, file_name, sheet_name, row, value):#把结果写回到表中
        #wb = load_workbook(file_name)
        #sheet_name = wb[sheet_name]
        #sheet.cell(row, 5).value = value
        #wb.save(file_name)
(2)方法二:根据坐标取出用到的单元格的值
class DoExcel2(object):

    def __init__(self, file_name, sheet_name):
        self.file_name = file_name
        self.sheet_name = sheet_name
        self.sheet_obj = load_workbook(self.file_name)[self.sheet_name]
        #获取一个表单对象
        self.max_row = self.sheet_obj.max_row

    def get_data(self, i, j):
        return self.sheet_obj.cell(i, j).value
        #根据传入的坐标来传值
(3)方法三:表数据中加了标题,通过标题来定位数据(和方法一相同,加了标题)
class DoExcel3(object):

    def __init__(self, file_name, sheet_name):
        self.file_name = file_name
        self.sheet_name = sheet_name

    def get_header(self):
        wb = load_workbook(self.file_name)
        sheet = wb[self.sheet_name]
        '''获取第一行标题'''
        header = []
        for column in range(1, sheet.max_column + 1):
            header.append(sheet.cell(1, column).value)

        return header

    def get_data(self):
        #从配置文件读取mode
        mode = ReadConfig().read_config('case.config', 'MODE', 'mode')
        wb = load_workbook(self.file_name)
        sheet = wb[self.sheet_name]
        max_row = sheet.max_row
        header = self.get_header() #拿到header

        test_data = []
        for row in range(2, max_row + 1):
            sub_data = {}
            for column in range(1, sheet.max_column + 1):
                sub_data[header[column - 1]] = sheet.cell(row, column).value
            test_data.append(sub_data)
        #根据mode值去判断
        if mode == 'all':#默认执行所有用例
            final_data = test_data
        else:#[1, 2, 3, 4]
            final_data = []
            for item in test_data:#对test_data所有的测试数据进行遍历
                if item['case_id'] in eval(mode):
                    final_data.append(item)

        return final_data#返回获取到的数据
if __name__ == '__main__':

    print(DoExcel('data.xlsx', 'login_data').get_data())
补充:上述通过配置文件读取执行用例的条件
#case.config文件举例
[MODE]
mode = all

[PYTHON]
num = 66
name = ['aaa','bbb']
import configparser
#section(中括号[]) option value   #(key:value)

cf = configparser.ConfigParser()
cf.read('case.config', encoding='utf-8')

#读取配置文件的数据
#读取方法一
# res_1 = cf.get('MODE', 'mode')
# print(res_1)
#
# #读取方法二
# res_2 = cf['MODE']['mode']
# print(res_2)
# print(cf.sections())
# print(cf.items('MODE'))#每一组元素都存在一个元组里面,然后嵌套在一个列表里面

#数据类型讨论问题----都是字符串---->eval()转换字符串
print(type(cf.get('PYTHON', 'num')))
print(type(cf.get('PYTHON', 'name')))#配置文件里的内容输出都是字符串
补充:ddt
import unittest
from ddt import ddt, data, unpack

test_data = [[1, 4], [2, 3]]

@ddt#装饰测试类
class TestMath(unittest.TestCase):

    # @data(test_data)#装饰测试方法 拿到几个数据 就执行几条用例 一条数据执行1次
    # #@data(*test_data) #拆分开来 执行2次,一个*只能托一层外套
    # #unpack 根据逗号进行拆分,不止一个参数
    @data(test_data)
    @unpack#如果unpack后的参数 少于5个 推荐用unpack
    #要注意参数不对等的情况,提供对应个数的参数来接收变量
    #如果你要对字典进行unpack的 参数名与你的字典key对应
    def test_print_data(self, item):
        print('item', item)
    # def test_print_data(self, a, b):
    #     print('a', a)
    #     print('b', b)

相关文章

网友评论

      本文标题:unittest小结--多种方式

      本文链接:https://www.haomeiwen.com/subject/znscgctx.html