1. 程式人生 > 程式設計 >PHP 實現base64編碼檔案上傳出現問題詳解

PHP 實現base64編碼檔案上傳出現問題詳解

一、openpyxl介紹安裝

1.為什麼要學Excel

存測試資料

有時候有大批量的資料,存到TXT檔案裡面顯然不是最佳的方式,我們可以存到Excel裡面去,第一方便我們存資料和做資料,另一方面方便我們讀取資料,比較明朗。測試的時候就從資料庫中讀取出來,這點是非常重要的。

存測試結果

可以批量把結果存入到Excel中,也是比較好整理資料點,比我們的TXT要好。

2.安裝openpyxl

python中與excel操作相關的模組:

  • xlrd庫:從excel中讀取資料,支援xls、xlsx
  • xlwt庫:對excel進行修改操作,不支援對xlsx格式的修改
  • xlutils庫:在xlw和xlrd中,對一個已存在的檔案進行修改。
  • openpyxl:主要針對xlsx格式的excel進行讀取和編輯。

官方說法:網址:http://www.python-exceel.org/

安裝方式:pip install openxl

3.Excel中的三大物件

  • WorkBook:工作簿物件
  • Sheet:表單物件
  • Cell:表格物件

二、openpyxl對Excel的操作

  • 建立一個工作薄:wb = openpyxl.Workbook()
  • 新增一個sheet表單:wb.create_sheet('test_case')
  • 儲存case.xlsx檔案:wb.save('cases.xlsx')
  • 開啟工作簿:wb = openpyxl.load_workbook('cases.xlsx')
  • 選取表單:sh = wb['Sheet1'
  • 讀取第一行、第一列的資料:ce = sh.cell(row = 1,column = 1)
  • 按行讀取資料:row_data = list(sh.rows)
  • 關閉工作薄:wb.close()
  • 按列讀取資料:columns_data = list(sh.columns)
  • 寫入資料之前,該檔案一定要處於關閉狀態
  • 寫入第一行、第四列的資料 value = 'result':sh.cell(row = 1,column = 4,value = 'result')
  • 獲取最大行總數、最大列總數:sh.max_row、sh.max_column
  • del 刪除表單的用法:del wb['sheet_name']
  • remove 刪除表單的用法:sh = wb['sheet_name'] wb.remove(sh)
  • import openpyxl
    # 建立一個工作簿
    wb = openpyxl.Workbook()
    # 建立一個test_case的sheet表單
    wb.create_sheet('test_case')
    # 儲存為一個xlsx格式的檔案
    wb.save('cases.xlsx')
    # 讀取excel中的資料
    # 第一步:開啟工作簿
    wb = openpyxl.load_workbook('cases.xlsx')
    # 第二步:選取表單
    sh = wb['Sheet1']
    # 第三步:讀取資料
    # 引數 row:行  column:列
    ce = sh.cell(row = 1,column = 1)   # 讀取第一行,第一列的資料
    print(ce.value)
    # 按行讀取資料 list(sh.rows)
    print(list(sh.rows)[1:])     # 按行讀取資料,去掉第一行的表頭資訊資料
    for cases in list(sh.rows)[1:]:
        case_id =  cases[0].value
        case_excepted = cases[1].value
        case_data = cases[2].value
        print(case_excepted,case_data)
    # 關閉工作薄
    wb.close()

三.封裝一個讀取用例的excel類:用來實現讀取資料和寫入資料的功能

cases.xlsx的測試資料:

1.按行讀取資料,儲存在列表中

import openpyxl
class Case: #這個類用來儲存用例的
    __slots__ = [] #特殊的類屬性,可以用來限制這個類建立的例項屬性新增 可寫可不寫
    pass

class ReadExcel(object): #讀取excel資料的類
    def __init__(self,file_name,sheet_name):
        """
        這個是用來初始化讀取物件的
        :param file_name: 檔名 ---> str型別
        :param sheet_name: 表單名 ———> str型別
        """
        # 開啟檔案
        self.wb = openpyxl.load_workbook(file_name)
        # 選擇表單
        self.sh = self.wb[sheet_name]
    def read_data_line(self):
        #按行讀取資料轉化為列表
        rows_data = list(self.sh.rows)
        # print(rows_data)
        # 獲取表單的表頭資訊
        titles = []
        for title in rows_data[0]:
            titles.append(title.value)
        # print(titles)
        #定義一個空列表用來儲存測試用例
        cases = []
        for case in rows_data[1:]:
            # print(case)
            data = []
            for cell in case: #獲取一條測試用例資料
                # print(cell.value)
                data.append(cell.value)
                # print(data)
                #判斷該單元格是否為字串,如果是字串型別則需要使用eval();如果不是字串型別則不需要使用eval()
                if isinstance(cell.value,str):
                    data.append(eval(cell.value))
                else:
                    data.append(cell.value)
                #將該條資料存放至cases中
            # print(dict(list(zip(titles,data))))
                case_data = dict(list(zip(titles,data)))
                cases.append(case_data)
        return cases
if __name__ == '__main__':
    r = ReadExcel('cases.xlsx','Sheet1')
    data1 = r.read_data_line()
    print(data1)

2.按行讀取資料,儲存在物件中

import openpyxl
class Case:
    pass
class ReadExcel(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sh = self.wb[sheetname]
    def read_data_obj(self):
        """
        按行讀取資料  每條用例儲存在一個物件中
        :return:
        """
        rows_data = list(self.sh.rows)
        # print(rows_data)
        # 獲取表單的表頭資訊
        titles = []
        for title in rows_data[0]:
            titles.append(title.value)
        # print(titles)
        # 定義一個空列表用來儲存測試用例
        cases = []
        for case in rows_data[1:]:
            # print(case)
            #建立一個Case類的物件,用來儲存用例資料
            case_obj = Case()
            data = []
            for cell in case:  # 獲取一條測試用例資料
                # print(cell.value)
                # data.append(cell.value)
                # print(data)
                if isinstance(cell.value,str):  # 判斷該單元格是否為字串,如果是字串型別則需要使用eval();如果不是字串型別則不需要使用eval()
                    data.append(eval(cell.value))
                else:
                    data.append(cell.value)
            # 將該條資料存放至cases中
            # print(dict(list(zip(titles,data))))
            case_data = list(zip(titles, data))
            # print(case_data)
            for i in case_data:
                setattr(case_obj,i[0],i[1])
            # print(case_obj)
            # print(case_obj.case_id,case_obj.data,case_obj.excepted)
            cases.append(case_obj)
        return cases
if  __name__ == '__main__':
    r = ReadExcel('cases.xlsx','Sheet1')
    res = r.read_data_obj()
    for i in res:
        print(i.caseid, i.excepted, i.data)

3.將測試用例封裝到列表中,讀取指定列的資料

import openpyxl
class Case:
    pass
class ReadExcelZy(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]
        # list1 引數為一個列表,傳入的是指定讀取資料的列,比如[1,2,3]
        # 每一行[1,3,5]列的資料,讀取出來就作為一條測試用例,放在字典中
        # 所有的用例放在列表中並且進行返回
    def read_data(self,list1):
        """
        :param list1:  list--->要讀取列   list型別
        :return:    返回一個列表,每一個元素為一個用例(用例為dict型別)
        """
        # 獲取最大的行數
        max_r = self.sheet.max_row
        cases = []   #定義一個空列表,用來存放所有的用例資料
        titles = []   #定義一個空列表,用來存放表頭
        # 遍歷所有的行資料
        for row in range(1,max_r+1):
            if row != 1:      #判斷是否是第一行
                case_data = [] #定義一個空列表,用來存放該行的用例資料
                for column in list1:
                    info = self.sheet.cell(row,column).value
                    # print(info)
                    case_data.append(info)
                    # print(list(zip(titles,case_data)))
                case = dict(zip(titles,case_data))  #將該條資料和表頭進行打包組合,作用相當於dict(list(zip(titles,case_data)))
                # print(case)
                cases.append(case)
                # print(cases)
            else:   #獲取表頭資料
                for column in list1:
                    title = self.sheet.cell(row,column).value
                    titles.append(title)
                # print(titles)
        return cases
if __name__ == '__main__':
    r = ReadExcelZy("cases.xlsx","Sheet1")
    res = r.read_data([1,2,3])
    for o in res:
        print(o['caseid'],o['data'],o['excepted'])

4.將測試用例封裝到物件中,讀取指定列的資料

import openpyxl
class Case:
    pass
class ReadExcelZy(object):
    def __init__(self,filename,sheetname):
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]

        # list1 引數為一個列表,傳入的是指定讀取資料的列,比如[1,2,3]
        # 每一行[1,3,5]列的資料,讀取出來就作為一條測試用例,放在字典中
        # 所有的用例放在物件中並且進行返回
    def read_data_obj(self,list2):
        max_r1 = self.sheet.max_row      #獲取最大行數
        cases = []
        titles = []      #用來存放表頭資料
        for row in range(1,max_r1+1):
            if row != 1:
                case_data = []
                for column in list2:
                    info = self.sheet.cell(row,column).value
                    # print(info)
                    case_data.append(info)
                cases_data = list(zip(titles,case_data))
                #將一條用例存到一個物件中(每一列對應物件的一個屬性)
                case_obj = Case()
                for i in cases_data:
                    # print(i)
                    setattr(case_obj,i[0],i[1])
                # print(case_obj.caseid,case_obj.excepted,case_obj.data)
                cases.append(case_obj)
            else:
                for column in list2:
                    title = self.sheet.cell(row,column).value
                    titles.append(title)
        return cases
if __name__ == '__main__':
    r = ReadExcelZy("cases.xlsx","Sheet1")
    res = r.read_data_obj([1,2,3])
    for i in res:
        print(i.caseid,i.data,i.excepted)

5.優化第4部分程式碼,將設定物件屬性寫在初始化方法中(封裝Excel類讀取資料最常用的方法)

import openpyxl
class Case:  # 這個類用來儲存用例的
    def __init__(self, attrs):
        """
        初始化用例
        :param attrs:zip型別——>[{key,value},(key1,value1)......]
        """
        for i in attrs:
            setattr(self, i[0], i[1])
class ReadExcel(object):
    def __init__(self, filename, sheetname):
        """
        定義需要開啟的檔案及表名
        :param filename:   檔名
        :param sheetname:  表名
        """
        self.wb = openpyxl.load_workbook(filename)
        self.sheet = self.wb[sheetname]
    def read_data_obj_new(self, list2):
        # 獲取最大行數
        max_r1 = self.sheet.max_row
        cases = []
        # 用來存放表頭資料
        titles = []
        for row in range(1, max_r1 + 1):
            if row != 1:
                case_data = []
                for column in list2:
                    info = self.sheet.cell(row, column).value
                    # print(info)
                    case_data.append(info)
                case = list(zip(titles, case_data))
                # 新建物件時,將物件傳給Case類
                case_obj = Case(case)
                # print(case_obj.caseid,case_obj.excepted,case_obj.data)
                cases.append(case_obj)
            else:
                # 獲取表頭
                for column in list2:
                    title = self.sheet.cell(row, column).value
                    titles.append(title)
                if None in titles:
                    raise ValueError("傳入的表頭的資料有顯示為空")
        return cases
if __name__ == '__main__':
    r = ReadExcel('cases.xlsx', 'Sheet1')
    res1 = r.read_data_obj_new([1, 2, 3])
    for i in res1:
        print(i.caseid, i.data, i.excepted)

三.完整流程的程式碼

一、將測試資料引數化

import unittest
from python.register_new.register import register
from python.register_new.register_testcase_new import RegisterTestCase
from HTMLTestRunnerNew import HTMLTestRunner
class RegisterTestCase(unittest.TestCase):
    # 初始化測試用例
    def __init__(self,modethod_name,excepted,data):
        # modethod_name 測試用例方法名
        super().__init__(modethod_name)
        # excepted 測試用例的預期結果
        self.excepted = excepted
        # data 測試用例引數值
        self.data = data

    def setUp(self):
        print("準備測試環境,執行測試用例之前會執行此操作")

    def tearDown(self):
        print("還原測試環境,執行完測試用例之後會執行此操作")

    def test_register(self):
        res = register(*self.data)
        try:
            self.assertEquals(self.excepted,res)
        except AssertionError as e:
            print("該條測試用例執行未通通過")
            raise e
        else:
            print("該條測試用例執行通過")

# 建立測試套件
suite = unittest.TestSuite()

# 將測試用例新增至測試套件中
case = [{'excepted':'{"code": 1, "msg": "註冊成功"}','data':'('python1', '123456','123456')'},
        {'excepted':'{"code": 0, "msg": "兩次密碼不一致"}','data':'('python1', '1234567','123456')'}]
for case in cases:
    suite.addTest(RegisterTestCase('test_register',case['excepted'],case['data']))

# 執行測試套件,生成測試報告
with open("report.html",'wb') as f:
    runner = HTMLTestRunner(
        stream = f,
        verbosity = 2,
        title = 'python_test_report',
        description = '這是一份測試報告',
        tester = 'WL'
    )
    runner.run(suite)

二.將呼叫封裝好的Excel類的完整程式碼流程

import unittest
from python.register_new.register import register
from python.register_new.register_testcase_new import RegisterTestCase
from HTMLTestRunnerNew import HTMLTestRunner
from python.readexcel import ReadExcel


class RegisterTestCase(unittest.TestCase):
    # 初始化測試用例
    def __init__(self, modethod_name, excepted, data):
        # modethod_name 測試用例方法名
        super().__init__(modethod_name)
        # excepted 測試用例的預期結果
        self.excepted = excepted
        # data 測試用例引數值
        self.data = data

    def setUp(self):
        print("準備測試環境,執行測試用例之前會執行此操作")

    def tearDown(self):
        print("還原測試環境,執行完測試用例之後會執行此操作")

    def test_register(self):
        res = register(*self.data)
        try:
            self.assertEquals(self.excepted, res)
        except AssertionError as e:
            print("該條測試用例執行未通通過")
            raise e
        else:
            print("該條測試用例執行通過")


# 建立測試套件
suite = unittest.TestSuite()
# 呼叫封裝好的讀取資料的Excel類,獲取測試資料
r1 = ReadExcel('cases.xlsx', 'Sheet1')
cases = r1.read_data_obj_new([2, 3])
# 將測試用例新增至測試套件中
for case in cases:
    # 需要使用eva()函式對except和data進行自動識別
    suite.addTest(RegisterTestCase('test_register', eval(case.excepted), eval(case.data)))
# 執行測試套件,生成測試報告
with open("report.html", 'wb') as f:
    runner = HTMLTestRunner(
        stream=f,
        verbosity=2,
        title='python_test_report',
        description='這是一份測試報告',
        tester='WL')
    runner.run(suite)