一、什么是配置文件?

  • 配置文件示例  

  1. [mysql]
  2. default-character-set = utf8
  3.  
  4. [mysqld]
  5. port = 3306
  6. basedir = c:\mysql-5.7.25-winx64\mysql-5.7.25-winx64
  7. daradir = c:\mysql-5.7.25-winx64\mysql-5.7.25-winx64\data
  8. max_connections = 200
  9. character-set-server = utf8
  10. default-storage-engine = INNODB
  11. explicit_defaults_for_timestamp = true
  • 为什么要做配置文件?

  所有的代码和配置都变成模块化可配置化,这样就提高了代码的复用性,不用每次都去修改代码内部。

  • 场景举例

     1、多处地方需要使用同一个参数,这时候最好是配置化,这样改一处就可以了

     2、如果是经常变化的变量,我们也可以做这个配置。---> 与参数化要区分开来

  • python中常见的配置文件格式

   .ini、.conf、.cfg结尾的文件

  • 配置对象

    • section
    • option

二、ConfigParser模块

掌握一些比较基础的用法:跟file文件一样,要先打开才能进行读取操作

  • 实例化ConfigParse对象:cf = configParser.ConfigParser()

  • 打开配置文件:cf.read(配置文件名称或者地址)

  • 常用方法:

    • read(filename)  直接读取文件内容
    • sections()  得到所有的section,并以列表的形式返回
    • options(section)  得到该section的所有option
    • items(section)  得到该section的所有键值对
    • get(section,option)  得到该section中option的值,返回类型为string
    • getint(section,option)  得到该section中option的值,返回为int类型,还有相应的getboolean()和getfloat()
  • 练习

  1. import configparser
  2. # 实例化ConfigParser对象
  3. conf = configparser.ConfigParser()
  4. # 打开配置文件
  5. cf = conf.read("my.conf",encoding = 'utf8')
  6. # 根据section和option得到option的值
  7. a = conf.get('mysqld','port')
  8. print(a)
  9.  
  10. # 得到所有的section,并以列表的形式返回
  11. b = conf.sections()
  12. print(b)
  13. # 得到该section的所有option
  14. c = conf.options('mysqld')
  15. print(c)
  16. # 得到该section所有的键值对
  17. d = dict(conf.items("mysql"))
  18. print(d)

输出结果为:

  • 封装一个读取配置文件的类

  1. import configparser
  2. """
  3. 为什么要封装?
  4. 封装是为了使用起来更加方便,便于再次修改
  5. 封装的需求?
  6. 封装成什么样子才能达到我们的目的
  7. 封装的原则:
  8. 写死的固定数据(变量),可以封装成雷属性
  9. 实现某个功能的代码封装成方法
  10. 在各个办法中都要用到的数据,抽离出来作为实例属性
  11. """
  12.  
  13. # 封装前 读取数据(三部曲)
  14. # 实例化ConfigParser对象
  15. # conf = configparser.ConfigParser()
  16. # 打开配置文件
  17. # conf.read("config.ini",encoding='utf8')
  18. # # 根据section和option得到option的值
  19. # conf.get('excel','file_name')
  20.  
  21. class ReadConfig(configparser.ConfigParser):
  22.  
  23. def __init__(self):
  24. # 实例化对象
  25. super().__init__()
  26. # 加载文件
  27. self.read(r"E:\python_api_test\API_Test_v4_config\conf\config.ini",encoding='utf8')
  28.  
  29. conf = ReadConfig()
  • 在其他模块调用封装好的配置文件时:from xxxx.xxxx.config import conf

三、将配置文件集成到单元测试中

1、项目结构

  • common:这个目录用来存放的是自己封装的类
  • conf:这个目录用来存放配置文件
  • librarys:这个目录用来存放已封装好的模块(HTMLtestrunner、ddt)
  • logs:这个目录用来存放日志文件
  • data:这个目录用来存放excel的测试用例数据
  • reposts:这个目录用来存放生成的的测试报告
  • testcases:这个目录用来存放所有的测试用例模块

2、各项目层的结构图

3、各项目层的具体代码

  • common层(包括config.py文件、mylogging_v3.py文件、read_excel_data.py文件)

新建config.py文件

  1. import configparser
  2. """
  3. 为什么要封装?
  4. 封装是为了使用起来更加方便,便于再次修改
  5. 封装的需求?
  6. 封装成什么样子才能达到我们的目的
  7.  
  8. 封装的原则:
  9. 写死的固定数据(变量),可以封装成雷属性
  10. 实现某个功能的代码封装成方法
  11. 在各个办法中都要用到的数据,抽离出来作为实例属性
  12. """
  13.  
  14. # 封装前 读取数据(三部曲)
  15. # 实例化ConfigParser对象
  16. # conf = configparser.ConfigParser()
  17. # 打开配置文件
  18. # conf.read("config.ini",encoding='utf8')
  19. # # 根据section和option得到option的值
  20. # conf.get('excel','file_name')
  21. class ReadConfig(configparser.ConfigParser):
  22. def __init__(self):
  23. # 实例化对象
  24. super().__init__()
  25. # 加载文件
  26. self.read(r"E:\python_api_test\API_Test_v4_config\conf\config.ini",encoding='utf8')
  27. conf = ReadConfig()

新建mylogging_v3.py文件

  1. import logging
  2. from API_Test_v4_config.common.config import conf
  3.  
  4. # 日志收集器的名称
  5. logger_name = conf.get('log','logger_name')
  6. # 日志收集器的级别
  7. level = conf.get('log','level').upper()
  8. # 输出到控制台的日志级别
  9. sh_level = conf.get('log','sh_level').upper()
  10. # 输出到文件的日志级别
  11. fh_level = conf.get('log','fh_level').upper()
  12. # 日志保存的文件
  13. log_file_path = conf.get('log','log_file_path')
  14.  
  15. class MyLogging(object):
  16. def create_logger(*args,**kwargs):
  17. # 创建自己的日志收集器
  18. my_log = logging.getLogger(logger_name)
  19. # 设置收集的日志等级,设置为DEBUG等级
  20. my_log.setLevel(level)
  21. # 日志输出渠道
  22. # 创建一个日志输出渠道(输出到控制台),并且设置输出的日志等级为INFO以上
  23. l_s = logging.StreamHandler()
  24. l_s.setLevel(sh_level)
  25. # 创构建一个日志输出渠道(输出到文件),并且设置输出的日志等级为DEBUG以上
  26. l_f = logging.FileHandler(log_file_path,encoding='utf8')
  27. l_f.setLevel(fh_level)
  28. #将日志输出渠道添加到日志收集器中
  29. my_log.addHandler(l_s)
  30. my_log.addHandler(l_f)
  31. # 设置日志输出的格式
  32. ft = "%(asctime)s - [%(filename)s -->line:%(lineno)d] - %(levelname)s: %(message)s"
  33. ft = logging.Formatter(ft)
  34. # 设置控制台和日志文件输出日志的格式
  35. l_s.setFormatter(ft)
  36. l_f.setFormatter(ft)
  37. return my_log
  38.  
  39. def debug(self,msg):
  40. self.my_log.debug(msg)
  41.  
  42. def info(self,msg):
  43. self.my_log.info(msg)
  44.  
  45. def warning(self,msg):
  46. self.my_log.warning(msg)
  47.  
  48. def error(self,msg):
  49. self.my_log.error(msg)
  50.  
  51. def critical(self,msg):
  52. self.my_log.critical(msg)
  53.  
  54. #日志输出
  55. m_log = MyLogging()
  56. # 创建日志收集器
  57. logger = m_log.create_logger()

新建read_excel_data.py文件

  1. import openpyxl
  2. class Case:
  3. def __init__(self,arrts):
  4. for item in arrts:
  5. setattr(self,item[0],item[1])
  6. class ReadExcel(object):
  7. def __init__(self,filename,sheetname):
  8. """
  9. 定义需要打开的文件及表名
  10. :param filename: 文件名
  11. :param sheetname: 表名
  12. """
  13. self.wb = openpyxl.load_workbook(filename) # 打开工作簿
  14. self.sheet = self.wb[sheetname] # 选定表单
  15. self.filename = filename
  16.  
  17. # 特殊的魔术方法,在对象销毁之后执行的
  18. def __del__(self):
  19. # 关闭文件
  20. self.wb.close()
  21. def read_data_line(self):
  22. #按行读取数据转化为列表
  23. rows_data = list(self.sh.rows)
  24. # print(rows_data)
  25. # 获取表单的表头信息
  26. titles = []
  27. for title in rows_data[0]:
  28. titles.append(title.value)
  29. # print(titles)
  30. #定义一个空列表用来存储测试用例
  31. cases = []
  32. for case in rows_data[1:]:
  33. # print(case)
  34. data = []
  35. for cell in case: #获取一条测试用例数据
  36. # print(cell.value)
  37. data.append(cell.value)
  38. # print(data)
  39. #判断该单元格是否为字符串,如果是字符串类型则需要使用eval();如果不是字符串类型则不需要使用eval()
  40. if isinstance(cell.value,str):
  41. data.append(eval(cell.value))
  42. else:
  43. data.append(cell.value)
  44. #将该条数据存放至cases中
  45. # print(dict(list(zip(titles,data))))
  46. case_data = dict(list(zip(titles,data)))
  47. cases.append(case_data)
  48. return cases
  49.  
  50. def read_excel_obj_new(self,list1):
  51. """
  52. 按指定的列,读取excel中的数据,以列表的形式返回,列表中每个对象为一条测试用例,
  53. Excel中的表头为对象的属性,对应的数据为属性值。
  54. :param list1: list --->要读取的列[1,2,3...]
  55. :return: type:list--->[case_obj1,case_obj2.......]
  56. """
  57. # 从配置文件中读取的数据类型为string,需要转化为list
  58. list1 = eval(list1)
  59. # 判断传入的读取数据的列数是否为空,为空的话直接读取excel中所有的数据。
  60. if list1 == []:
  61. return self.read_data_line()
  62. # 获取表里面的最大行数
  63. max_row = self.sheet.max_row
  64. # 定义一个空列表,用来存放测试用例数据
  65. cases = []
  66. # 定义一个空列表,用来存放表头数据
  67. titles = []
  68. # 遍历所有的行数据
  69. for row in range(1,max_row+1):
  70. case_data = []
  71. if row != 1:
  72. for column in list1:
  73. info = self.sheet.cell(row,column).value
  74. # print(info)
  75. case_data.append(info)
  76. case = list(zip(titles,case_data))
  77. # print(case)
  78. case_obj = Case(case)
  79. cases.append(case_obj)
  80. else:
  81. for column in list1:
  82. title = self.sheet.cell(row,column).value
  83. titles.append(title)
  84. if None in titles:
  85. raise ValueError("表头的数据有显示为空")
  86. return cases
  87. def write_excel(self,row,column,msg):
  88. #写入数据
  89. self.sheet.cell(row=row,column=column,value=msg)
  90. self.wb.save(self.filename)
  • conf层(config.ini文件--->配置文件)

新建config.ini文件

  1. # log日志相关配置
  2. [log]
  3. # 日志收集器的名称
  4. logger_name = my_log
  5. # 日志收集器的级别
  6. level = DEBUG
  7. # 输出到控制台的日志级别
  8. sh_level = DEBUG
  9. # 输出到文件的日志级别()
  10. fh_level = debug
  11. # 日志保存的文件
  12. log_file_path = E:\python_api_test\API_Test_v4_config\logs\log.log
  13.  
  14. # 读取excel中测试用例数据相关的配置
  15. [excel]
  16. # 用例文件名称
  17. file_name = E:\python_api_test\API_Test_v4_config\data\cases.xlsx
  18. # sheet表单名称
  19. sheet_name = Sheet1
  20. # 读取表单中的列数(每条用例的数据) []空列表便是所有列
  21. read_colums = [1,2,3]
  22.  
  23. # 测试报告相关的配置
  24. [report]
  25. report_path = E:\python_api_test\API_Test_v4_config\reports\report.html
  26. report_name = python接口自动化测试报告
  27. report_tester = 测试
  • data层(cases.xlsx文件--->测试用例数据)

新建cases.xlsx文件

  • testcase层(register_testcase.py文件--->注册函数的测试用例)

新建register_testcase.py文件

  1. import unittest
  2. from API_Test_v4_config.register import register
  3. from API_Test_v4_config.common.read_excel_data import ReadExcel
  4. from ddt import ddt,data
  5. from API_Test_v4_config.common.mylogging_v3 import logger
  6. from API_Test_v4_config.common.config import conf
  7.  
  8. # 配置文件中读取excel相关数据
  9. file_name = conf.get('excel','file_name')
  10. sheet_name = conf.get('excel','sheet_name')
  11. read_colums = conf.get('excel','read_colums')
  12. # 读取excel中的数据
  13. wb = ReadExcel(file_name,sheet_name)
  14. cases = wb.read_excel_obj_new(read_colums)
  15.  
  16. @ddt
  17. class RegisterTestCase(unittest.TestCase):
  18. def setUp(self):
  19. print("准备测试环境,执行测试用例之前会执行此操作")
  20. def tearDown(self):
  21. print("还原测试环境,执行完测试用例之后会执行此操作")
  22. @data(*cases)
  23. def test_register(self,case):
  24. self.row = case.caseid + 1
  25. res = register(*eval(case.data))
  26. try:
  27. self.assertEquals(eval(case.excepted),res)
  28. except AssertionError as e:
  29. res = "未通过"
  30. logger.error(e)
  31. raise e
  32. else:
  33. res = "通过"
  34. logger.info("该条测试用例的测试结果为:{}".format(res))
  35. finally:
  36. # 调用写入数据的方法,在excel中回写测试用例的执行结果
  37. wb.write_excel(row=self.row,column=4,msg=res)
  38.  
  39. if __name__ == '__main__':
  40. unittest.main()
  • 最外面层(register.py文件--->需要测试的功能函数、 register_suites.py--->执行测试套件)

新建register.py文件

  1. # 设计用例,对注册功能函数进行单元测试
  2. users = [{'user': 'python18', 'password': ''}]
  3. def register(username, password1, password2):
  4. # 注册功能
  5. for user in users: # 遍历出所有账号,判断账号是否存在
  6. if username == user['user']:
  7. # 账号存在
  8. return {"code": 0, "msg": "该账户已存在"}
  9. else:
  10. if password1 != password2:
  11. # 两次密码不一致
  12. return {"code": 0, "msg": "两次密码不一致"}
  13. else:
  14. # 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
  15. if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
  16. # 注册账号
  17. users.append({'user': username, 'password': password2})
  18. return {"code": 1, "msg": "注册成功"}
  19. else:
  20. # 账号密码长度不对,注册失败
  21. return {"code": 0, "msg": "账号和密码必须在6-18位之间"}

新建register_suites.py文件

  1. import unittest
  2. from HTMLTestRunnerNew import HTMLTestRunner
  3. from API_Test_v4_config.testcases import register_testcase
  4. from API_Test_v4_config.common.config import conf
  5.  
  6. # 第二步:创建测试套件
  7. suite = unittest.TestSuite()
  8. # 第三步:将测试用例加载到测试套件中
  9. loader = unittest.TestLoader()
  10. # 通过测试用例类来添加测试用例
  11. # suite.addTest(loader.loadTestsFromTestCase(RegisterTestCase))
  12. # 通过模块来添加测试用例
  13. suite.addTest(loader.loadTestsFromModule(register_testcase))
  14. # 添加测试用例,通过路径加载测试用例目录下的所有模块
  15. # suite.addTest(loader.discover("E:\\python_api_test\\API_Test_v4_config\\testcases"))
  16. #第四步:执行测试套件,生成测试报告
  17. # 读取配置文件中report相关的配置信息
  18. report_path = conf.get("report",'report_path')
  19. report_name = conf.get('report','report_name')
  20. report_tester = conf.get('report','report_tester')
  21.  
  22. with open(report_path,'wb') as f:
  23. runner = HTMLTestRunner(
  24. stream = f,
  25. verbosity = 2,
  26. title = 'python_18_report',
  27. description = report_name,
  28. tester = report_tester
  29. )
  30. runner.run(suite)

  

python自动化测试—配置文件的使用的更多相关文章

  1. Python自动化测试 -ConfigParser模块读写配置文件

    C#之所以容易让人感兴趣,是因为安装完Visual Studio, 就可以很简单的直接写程序了,不需要做如何配置. 对新手来说,这是非常好的“初体验”, 会激发初学者的自信和兴趣. 而有些语言的开发环 ...

  2. 《自拍教程5》Python自动化测试学习思路

    前提:熟悉测试业务及流程 任何Python自动化测试的前提,都是必须先熟悉实际测试业务. 任何脱离实际测试业务的自动化都是噱头且无实际意义! 测试的基本流程基本是: 测试需求分析,测试用例设计与评审, ...

  3. Python自动化测试面试题-Selenium篇

    目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...

  4. python自动化测试(2)-自动化基本技术原理

    python自动化测试(2) 自动化基本技术原理 1   概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...

  5. python自动化测试(4)-使用第三方python库技术实现

    python自动化测试(4)-使用第三方python库技术实现 1   概述 关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 ...

  6. python自动化测试(3)- 自动化框架及工具

    python自动化测试(3) 自动化框架及工具 1   概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到 ...

  7. (学习网址)Python 自动化测试

    1.Python自动化测试地址 http://www.wtoutiao.com/author/python-selenium.html 2.unittest参考网址: 1)python自动化测试报告H ...

  8. python 自动化测试资料

    python 自动化测试资料: http://yunpan.cn/QXVvwVJsAsPnb

  9. selenium + python 自动化测试环境搭建

    selenium + python 自动化测试 —— 环境搭建 关于 selenium Selenium 是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操 ...

随机推荐

  1. datagrid数据清空

    方法一: 不管是url方式还是加载本地数据的方式,均可以直接使用loadData方法清空数据,一行代码就可以清空: $('#tt').datagrid('loadData',{total:0,rows ...

  2. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  3. leetcode 137单词接龙

    直接层序遍历,结果有部分测试样例超时: class Solution { public: int ladderLength(string beginWord, string endWord, vect ...

  4. Spliterator介绍

    一.Spliterator Spliterator<T> trySplit();trySplit接口就相当于我们之前写的AccumulatorRecursiveTask类里面的分割任务,如 ...

  5. nginx不记录指定文件类型的日志

    1.指定记录文件日志记录的内容. vim /usr/local/nginx/conf/nginx.conf如下部分: log_format dd '$remote_addr $http_x_forwa ...

  6. LoadRunner 技巧之 自动关联

    LoadRunner 技巧之 自动关联 这一节讲loadunner 关联的问题,其实这个东西理解起来简单,但说起来比较麻烦. 关联的原理:                               ...

  7. Oracle 笔记(三)

    Oracle的数据库对象 七大对象:用户.表.约束.序列.视图.同义词和索引 知识点一:用户  -  User  -  账户.管理员-一切对象的宿主 1.创建用户 ???? 2.授权 ???? 授权+ ...

  8. 【SSM】---Spring+SpringMVC+Mybatis框架整合

    参考 百度经验 https://jingyan.baidu.com/article/2a1383288a85a9074a134f1b.html CSDN http://blog.csdn.net/ge ...

  9. Linux进程的虚拟内存

    简介 用户进程的虚拟地址空间是Linux的一个重要的抽象:它为每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会干扰到其他进程内存中的内容. 每个应用程序都有自己的线性地址空间,与所 ...

  10. Docker安装报错

    这是由于overlay2不支持造成的,所以我们要关闭它. 解决办法: vim /etc/sysconfig/docker    (修改文件) DNS='--selinux-enabled --log- ...