python基础之类与对象的应用-操作excel

python操作excel

openpyxl

  • 前置说明

    • 安装openpyxl
    • 只支持.xlsx后缀
  • 创建excel

    • 手动创建:日常手动创建,双击excel图标
    • 代码创建:后面讲
  • 打开excel

    image
    from openpyxl import load_workbook
    # 1.打开excel
    wb=load_workbook("test.xlsx")
    # 2.定位表单
    sheet=wb["test001"] #必须传入表单名,返回表单对象
    # 3.定位但单元格 行列值
    value=sheet.cell(1,1).value #第1行第1列的单元格.值
    #打印单元格的值
    print(value)
    #最大行
    print("最大行:",sheet.max_row)
    #最大列
    print("最大列:",sheet.max_column)
    
image
  • 数据从excel中拿出来是什么类型

    #数据从excel中拿出来是什么类型
    print("学号是:",sheet.cell(1,1).value,type(sheet.cell(1,1).value))
    print("分数是:",sheet.cell(1,2).value,type(sheet.cell(1,2).value))
    print("不及格率:",sheet.cell(1,3).value,type(sheet.cell(1,3).value))
    print("住址是:",sheet.cell(1,4).value,type(sheet.cell(1,4).value))
    

    结果是:数字还是数字,其他都是字符

    学号是: 18 <class 'int'>
    分数是: {"语文":90,"数字":98,"生物":78} <class 'str'>
    不及格率: 0.3 <class 'float'>
    住址是: 中国上海 <class 'str'>
    
  • eval() 把数据类型转换为原本的类型(仅限被转为字符串)

    s="True" #布尔值转为字符串
    print(type(s))  #<class 'str'>
    a=eval(s)#使用eval函数,将字符串类型转为原来的布尔类型
    print(type(a)) #<class 'bool'>
    
  • 封装一个获取excel值的工具类

    • 方法一:把数据一次取出,调用一次取出sheet所有数据(建议使用)

      from openpyxl import load_workbook
      class GetExcel:
          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]
              test_data=[] #每条数据要存在列表里
              for i in range(1, sheet.max_row+1):
                  sub_data={}
                  sub_data["age"]=sheet.cell(i,1).value
                  sub_data["score"]=sheet.cell(i,2).value
                  sub_data["percent"]=sheet.cell(i,3).value
                  sub_data["local"]=sheet.cell(i,4).value
                  test_data.append(sub_data)
              return test_data
      
      ex=GetExcel("test.xlsx","test001")
      print("测试数据:",ex.get_data())
      
    • 方法二:数据需要的时候再调用,调用一次取出一个单元格数据

    ```
    from openpyxl import load_workbook
    class DoExcel:
        """
        获取excel单元格的值
        """
        def __init__(self,file_name,sheet_name):
            """
            
            :param file_name: excel文件名
            :param sheet_name: sheet名
            """
            self.file_name=file_name
            self.sheet_name=sheet_name
    
        def get_excel(self,i,j):
            """
            
            :param i: 第几行
            :param j: 第几列
            :return: 返回对应单元格的值
            """
            wb=load_workbook(self.file_name)
            sheet=wb[self.sheet_name]
            return sheet.cell(i,j).value
        
         def get_max_row(self):
            """
            :return: sheet的最大行数
            """
            return self.sheet_obj.max_row

        def get_max_col(self):
            """
            :return: sheet的最大列数
            """
            return self.sheet_obj.max_column
            
    if __name__ == '__main__': #测试
        do=DoExcel("test.xlsx","test001")
        print(do.get_excel(1,1))
    ```

ddt

  • 安装ddt

  • ddt+unittest进行数据处理

    • 装饰器,暂时不用过多了解,不影响函数的情况下运行

    • ddt示例

      • @ddt 装饰测试类
      • @data 传入数据
      • @unpack 针对拿到的每一条数据,根据逗号进行拆分
      from ddt import ddt,unpack,data #导入ddt
      import unittest
      
      test_data=[1,4] #测试数据
      test_body=[[3,4],[2,3]]
      test_param=[[3,4],[2,3,7]]
      test_dict=[{"no":1,"name":"anny"},{"no":2,"name":"liu"}]
      
      @ddt #装饰测试类
      class TestMath(unittest.TestCase):
      
          @data(test_data)
          def test_print_data(self,item): #一条用例
              print("item:",item) #item: [1, 4]
              
          @data(*test_data) #装饰测试方法,拿到几条数据执行几条用例
          #不定长参数,俗称:脱外套
          def test_print_data_01(self,item):
              print("item:", item)  # item: 1  item: 4
          
          @data(*test_body) #脱外套只脱一层
          def test_print_data_02(self,item):
              print("item:",item) #item: [3, 4]  item: [2, 3]
              
          @data(*test_body)
          @unpack #针对拿到的每一条数据,根据逗号进行拆分,
          def test_print_data_03(self,a,b): #参数个数对应@npack拆分的个数,否则会报错
              print("a:",a)
              print("b:",b)
          # 输出: 
          # a: 3 b: 4
          # a: 2 b: 3
          
          
          @data(*test_param)
          @unpack
          #对于每一条测试用例的数据不等长时,可以采用默认值为None的方式接收避免报错
          def test_print_data_04(self,a=None,b=None,c=None):
              print("a:",a)
              print("b:",b)
              print("c:",c)    
          
          # 输出:
          # a: 3 b: 4 c: None
          # a: 2 b: 3 c: 7
          
          @data(*test_dict)
          @unpack
          #对字典进行unpack,参数名与你的字典key对应
          def test_print_data_05(self,no,name):
              print("no:",no)
              print("name:",name)
      
      • 使用unpack,data里的参数记得加*
      • 参数数据过长时,不建议用@unpack@data拿到后根据索引取值
      • 光标放在代码最后面再run,不然会报错
      • 对字典进行unpack,参数名与你的字典key对应

DDT与excel结合使用

  • 加载测试用例时,要使用TestLoader方法加载

总结unittest+excel

  • 两种方式
    • 超继承
    • ddt
  • 思路
    • 自己写的类
    • unittest单元测试:实现对自己写的类的测试
    • TestCase测试用例:self.assert断言、异常处理
    • 参数化:数据可以写在代码里,也可以写在excel里,excel使用openpyxl
      • 处理数据写成类 class GetExcel:
    • 数据与unittest结合起来
      • 超继承(原理要懂)
      • ddt (推荐使用)

配置文件

用例的可配置

有时,我们需要run不同程度的case、不同模块的case,所以需要case的一个可配置性

image
from openpyxl import load_workbook
class GetExcel:
    def __init__(self,file_name,sheet_name):
        self.file_name=file_name
        self.sheet_name=sheet_name

    def get_data(self,button="all"):
        """
        约定参数button,默认值为all。
        如果button值为“all”,则表示运行所有的case;
        如果button的值为一个case_id的列表,按照列表里的case_id进行运行。
        """
        wb=load_workbook(self.file_name)
        sheet=wb[self.sheet_name]
        test_data=[] #每条数据要存在列表里
        for i in range(2, sheet.max_row+1): #第一行是title,所以从第二行开始
            sub_data={}
            sub_data["case_id"] = sheet.cell(i, 1).value
            sub_data["mouble"] = sheet.cell(i, 2).value
            sub_data["age"]=sheet.cell(i,3).value
            sub_data["score"]=sheet.cell(i,4).value
            sub_data["percent"]=sheet.cell(i,5).value
            sub_data["local"]=sheet.cell(i,6).value
            test_data.append(sub_data)
        #对传入的button值进行判断
        if button == "all":
            finally_data=test_data
        else: #[1,2,3,4]
            finally_data=[]
            for item in test_data:
                if item["case_id"] in button:
                    finally_data.append(item)
        return finally_data

if __name__ == '__main__':
    ex=GetExcel("testdata.xlsx","Sheet1")
    print("测试数据:",ex.get_data()) #所有数据
    print("测试数据:", ex.get_data([1,3])) #第一条、第三条测试数据
配置文件

平常工作中可能会常见到.properties .config .ini .log4j(.log4j是java中的配置文件,python不用)结尾的文件,这些都是配置文件。python中有configparser模块可以去读取配置信息

  • 配置文件的规范

    • 新建一个文件以.config结尾,.properties.ini都可以
    • section 片段,配置文件中用[]区分,表示不同区域的数据
    • option=value,键值对,相当于key:value
    #case.config文件
    
    [BUTTON] #section
    button=all #option=value
    
    [PYTHON11] #section
    num=30  #option、value
    monitor=小月 #option=value 
    
  • 读取配置文件

    import configparser
    
    cf=configparser.ConfigParser()
    cf.read("case.config",encoding="utf-8")
    
    #获取配置文件的数据
    # 方法一
    res_1=cf.get("BUTTON","button") #(section,option)获取对应option的value
    print(res_1) #all
    # 方法二
    res_2=cf["BUTTON"]["button"]
    print(res_2) #all
    
    #获取所有的section
    res_3=cf.sections()
    print(res_3) #['BUTTON', 'PYTHON11']
    
    #获取option和value,每对以元组形式返回在一个列表里
    res_4=cf.items("PYTHON11")
    print(res_4) #[('num', '30'), ('monitor', '小月')]
    
  • 数据类型

    直接获取的数据类型都是字符串,使用eval()转换为原始数据类型

    res_1 = cf.get("BUTTON", "button")
    print(type(res_1)) #<class 'str'>
    res_2=cf.get("PYTHON11", "num")
    print(type(res_2)) #<class 'str'>
    
    #使用eval()转换为原始数据类型
    res_3 =cf.get("python11", "num")
    print(type(eval(res_3)))
    
  • 封装为一个工具类

    • tools文件夹中写入配置文件case.config
      [BUTTON]
      button=all
      #button=[1,2]
      
      
    • tools文件夹中写一个工具类class ReadConfig:
      import configparser
      
      class ReadConfig:
          def read_config(self,file_name,section,option):
              cf=configparser.ConfigParser()
              cf.read(file_name,encoding="utf-8")
              return eval(cf.get(section,option))
      
      
      if __name__ == '__main__':
          rc=ReadConfig()
          res=rc.read_config("case.config","BUTTON","button")
          print(res) #all
      
    • 原来的do_excel工具类要加以修改,加入读取配置文件
      from openpyxl import load_workbook
      from API_AUTO.tools import read_config
      
      class GetExcel:
          def __init__(self,file_name,sheet_name):
              self.file_name=file_name
              self.sheet_name=sheet_name
      
      def get_data(self):
          #读取配置文件
          button=read_config.ReadConfig().read_config("case.config","BUTTON","button")
          wb=load_workbook(self.file_name)
          sheet=wb[self.sheet_name]
          test_data=[] #每条数据要存在列表里
          for i in range(2, sheet.max_row+1):
              sub_data={}
              sub_data["case_id"] = sheet.cell(i, 1).value
              sub_data["mouble"] = sheet.cell(i, 2).value
              sub_data["age"]=sheet.cell(i,3).value
              sub_data["score"]=sheet.cell(i,4).value
              sub_data["percent"]=sheet.cell(i,5).value
              sub_data["local"]=sheet.cell(i,6).value
              test_data.append(sub_data)
      
          if button == "all":
              finally_data=test_data
          else: #[1,2,3,4]
              finally_data=[]
              for item in test_data:
                  if item["case_id"] in button:
                      finally_data.append(item)
          return finally_data
      
      if __name__ == '__main__':
      
          ex=GetExcel("testdata.xlsx","Sheet1")
          print("测试数据:",ex.get_data())
      
      这样根据给配置文件button配置不同的值,all或者case_id的列表,run不同的数据。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容