├── core
├── __init__.py
├── log.py
├── config.py
├── mysql.py
└── request.py
├── function
├── __init__.py
└── common.py
├── report
├── docs
│ └── index.md
└── mkdocs.yml
├── case
└── user.ini
├── run.py
├── constants.py
├── .gitignore
└── README.md
/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/function/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/report/docs/index.md:
--------------------------------------------------------------------------------
1 | # 欢迎来到测试报告
2 |
--------------------------------------------------------------------------------
/report/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: TezignAPI Test Report
2 | dev_addr: 0.0.0.0:8000
3 | site_dir: /site
4 | theme: readthedocs
5 |
6 | pages:
7 | - [index.md, Home]
--------------------------------------------------------------------------------
/case/user.ini:
--------------------------------------------------------------------------------
1 | [测试报告]
2 | report = '用户'
3 | reportName = 'user测试报告'
4 |
5 | [user_login]
6 | number = 1
7 | name = 登录
8 | method = post
9 | url = /user/login
10 | data = 'username=xxxxxxx&password=xxxxxx'
11 | headers = {'Content-Type':'application/x-www-form-urlencoded'}
12 | code = 0
--------------------------------------------------------------------------------
/core/log.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # author: 赫本z
4 | # 基础包: 日志服务
5 | import logging
6 |
7 | def get_logger():
8 | global logPath
9 | try:
10 | logPath
11 | except NameError:
12 | logPath = ""
13 | FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
14 | logging.basicConfig(level=logging.INFO, format=FORMAT)
15 | return logging
--------------------------------------------------------------------------------
/run.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # 执行包:runscript
4 |
5 | import function.common as func
6 |
7 | ApiTest = func.ApiTest()
8 |
9 | FILENAME = 'user.ini'
10 |
11 |
12 | """1.新建测试报告目录"""
13 | ApiTest.reset_report(filename=func.cs.CASE_PATH+FILENAME)
14 |
15 | """2.执行测试用例"""
16 | ApiTest.run_test(filename=func.cs.CASE_PATH+FILENAME)
17 |
18 | """3.统计测试报告结果"""
19 | ApiTest.write_report_result()
20 |
--------------------------------------------------------------------------------
/core/config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # author: 赫本z
4 | # 基础包:配置服务
5 |
6 | import ConfigParser
7 | import core.log as log
8 |
9 | config = ConfigParser.ConfigParser()
10 | logging = log.get_logger()
11 |
12 | def get_config(filename):
13 | """
14 | 获取文件配置
15 | :param filename: 配置文件名
16 | :return: None
17 | """
18 | global config
19 | try:
20 | config.read(filename)
21 | return True
22 | except Exception, e:
23 | logging.error("读取配置失败 %s" % e)
24 |
25 |
26 | def get_data(title, key):
27 | """
28 | 参数配置
29 | :param title: 配置文件的头信息
30 | :param key: 配置文件的key值
31 | :return: 配置文件的value
32 | """
33 | try:
34 | value = config.get(title, key)
35 | return value
36 | except Exception, e:
37 | logging.error("获取参数失败 %s" % e)
38 |
39 |
40 | def get_title_list():
41 | """
42 | 获取所有title
43 | :return: title list
44 | """
45 | try:
46 | title = config.sections()
47 | return str(title).decode("string_escape")
48 | # return '\n'.join(title)
49 | except Exception, e:
50 | logging.error("获取title信息失败 %s", e)
51 |
52 |
53 |
--------------------------------------------------------------------------------
/core/mysql.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # author: 赫本z
4 | # 基础包: MySQL
5 |
6 | import pymysql.cursors
7 | import core.log as log
8 |
9 |
10 | logging = log.get_logger()
11 | conn = None
12 |
13 | def connect(host, user, password, db, charset='utf8'):
14 | """
15 | 链接Mysql
16 | :param host: 地址
17 | :param user: 用户
18 | :param password: 密码
19 | :param db: 数据库名
20 | :param charset: 数据类型
21 | :return: 链接
22 | """
23 | global conn
24 | if conn == None:
25 | conn = pymysql.connect(host=host,
26 | user=user,
27 | password=password,
28 | db=db,
29 | charset=charset,
30 | cursorclass=pymysql.cursors.DictCursor)
31 | return conn
32 |
33 |
34 | def execute(sql):
35 | """
36 | 执行SQL
37 | :param sql: 执行的SQL
38 | :return: 影响行数
39 | """
40 | global conn
41 | try:
42 | with conn.cursor() as cursor:
43 | res = cursor.execute(sql)
44 | conn.commit()
45 | # 这里一定要写commit 不然提交的sql 都会被事务回滚
46 | return res
47 | except Exception, e:
48 | logging.error("sql is empty or error %s" % e)
49 |
50 |
51 | def close():
52 | """
53 | 关闭MySQL连接
54 | :return: None
55 | """
56 | global conn
57 | conn.close()
58 |
--------------------------------------------------------------------------------
/constants.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # 脚本功能:全部变量
4 |
5 | import sys
6 | import time
7 | import os
8 | reload(sys)
9 | sys.setdefaultencoding('utf8')
10 |
11 | TEST_URL = 'http://127.0.0.1:8080'
12 | OUT_PATH = os.path.dirname(os.path.dirname(__file__))
13 |
14 | REPORT_NAME = '测试报告'
15 | TITLE = '所有数据准备SQL'
16 |
17 | METHOD = 'method'
18 | URL = 'url'
19 | DATA = 'data'
20 | NAME = 'name'
21 | NUMBER = 'number'
22 | CODE = 'code'
23 | HEADERS = 'headers'
24 | REPORT = 'report'
25 | R_NAME = 'reportName'
26 |
27 | REPORT_PATH = OUT_PATH + "/api4code/report/docs/"
28 | YML_REPORT = OUT_PATH + "/api4code/report/mkdocs.yml"
29 |
30 |
31 | CASE_PATH = OUT_PATH + "/api4code/case/"
32 |
33 | #测试报告内容
34 | API_TEST_FAIL = """
35 | ```
36 | %s Case Fail
37 | Number: %s
38 | Method: %s
39 | Url: %s
40 | Headers:
41 | %s
42 | Data :
43 | %s
44 | 期望值 : %s
45 | 实际值 : %s
46 | ```
47 | """
48 |
49 | API_TEST_SUCCESS = """
50 | ```
51 | %s Case Pass
52 | Number: %s
53 | Method: %s
54 | Url: %s
55 | Headers:
56 | %s
57 | Data :
58 | %s
59 | 期望值 : %s
60 | 实际值 : %s
61 | ```
62 | """
63 |
64 | #报告结果统计
65 | RESULT_CONTENT = """
66 | 测试结果如下:
67 |
68 |
69 | | All |
70 | Pass |
71 | Fail |
72 |
73 |
74 | | %s |
75 | %s |
76 | %s |
77 |
78 |
79 | """
80 |
81 | NOW = '_' + time.strftime('%Y%m%d', time.localtime(time.time())) + '.md'
82 | PROJECT_TIME = time.strftime('%Y%m%d', time.localtime(time.time()))
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Python template
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | .hypothesis/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | .static_storage/
58 | .media/
59 | local_settings.py
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | target/
73 |
74 | # Jupyter Notebook
75 | .ipynb_checkpoints
76 |
77 | # pyenv
78 | .python-version
79 |
80 | # celery beat schedule file
81 | celerybeat-schedule
82 |
83 | # SageMath parsed files
84 | *.sage.py
85 |
86 | # Environments
87 | .env
88 | .venv
89 | env/
90 | venv/
91 | ENV/
92 | env.bak/
93 | venv.bak/
94 |
95 | # Spyder project settings
96 | .spyderproject
97 | .spyproject
98 |
99 | # Rope project settings
100 | .ropeproject
101 |
102 | # mkdocs documentation
103 | /site
104 |
105 | # mypy
106 | .mypy_cache/
107 |
108 | /.idea
--------------------------------------------------------------------------------
/core/request.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #-*- coding: UTF-8 -*-
3 | # 基础包:接口测试的封装
4 |
5 | import requests
6 | import core.log as log
7 | import json
8 |
9 | logging = log.get_logger()
10 |
11 | def change_type(value):
12 | """
13 | 对dict类型进行中文识别
14 | :param value: 传的数据值
15 | :return: 转码后的值
16 | """
17 | try:
18 | if isinstance(eval(value), str):
19 | return value
20 | if isinstance(eval(value), dict):
21 | result = eval(json.dumps(value))
22 | return result
23 | except Exception, e:
24 | logging.error("类型问题 %s", e)
25 |
26 |
27 | def api(method, url, data ,headers):
28 | """
29 | 自定义一个接口测试的方法
30 | :param method: 请求类型
31 | :param url: 地址
32 | :param data: 数据
33 | :param headers: 请求头
34 | :return: code码
35 | """
36 | global results
37 | try:
38 | if method == ("post" or "POST"):
39 | results = requests.post(url, data, headers=headers)
40 | if method == ("get" or "GET"):
41 | results = requests.get(url, data, headers=headers)
42 | # if method == "put":
43 | # results = requests.put(url, data, headers=headers)
44 | # if method == "delete":
45 | # results = requests.delete(url, headers=headers)
46 | # if method == "patch":
47 | # results == requests.patch(url, data, headers=headers)
48 | # if method == "options":
49 | # results == requests.options(url, headers=headers)
50 | response = results.json()
51 | code = response.get("code")
52 | return code
53 | except Exception, e:
54 | logging.error("service is error", e)
55 |
56 |
57 | def content(method, url, data, headers):
58 | """
59 | 请求response自己可以自定义检查结果
60 | :param method: 请求类型
61 | :param url: 请求地址
62 | :param data: 请求参数
63 | :param headers: 请求headers
64 | :return: message信息
65 | """
66 | global results
67 | try:
68 | if method == ("post" or "POST"):
69 | results = requests.post(url, data, headers=headers)
70 | if method == ("get" or "GET"):
71 | results = requests.get(url, data, headers=headers)
72 | if method == ("put" or "PUT"):
73 | results = requests.put(url, data, headers=headers)
74 | if method == ("patch" or "PATCH"):
75 | results = requests.patch(url, data, headers=headers)
76 | response = results.json()
77 | message = response.get("message")
78 | result = response.get("result")
79 | content = {"message": message, "result": result}
80 | return content
81 | except Exception, e:
82 | logging.error("请求失败 %s" % e)
83 |
--------------------------------------------------------------------------------
/function/common.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | # 业务包:通用函数
4 |
5 |
6 | import core.mysql as mysql
7 | import core.log as log
8 | import core.request as request
9 | import core.config as conf
10 | import constants as cs
11 | import os
12 |
13 | logging = log.get_logger()
14 |
15 |
16 | class ApiTest:
17 | """接口测试业务类"""
18 |
19 | def __init__(self):
20 | pass
21 |
22 | def prepare_data(self, host, user, password, db, sql):
23 | """
24 | 数据准备,添加测试数据
25 | :param host: 服务地址
26 | :param user: 用户
27 | :param password: 密码
28 | :param db: 数据库名
29 | :param sql: 执行的SQL
30 | :return:
31 | """
32 | mysql.connect(host, user, password, db)
33 | res = mysql.execute(sql)
34 | mysql.close()
35 | logging.info("Run sql: the row number affected is %s" % res)
36 | return res
37 |
38 | def get_prepare_sql(self, filename, key):
39 | """
40 | 获取预备执行的SQL
41 | :param title: 配置文件头信息
42 | :param key: 配置文件值
43 | :return: Value
44 | """
45 | try:
46 | conf.get_config(filename)
47 | value = conf.get_data(title=cs.TITLE, key=key)
48 | return value
49 | except Exception, e:
50 | logging.error("获取用例参数值失败 %s" % e)
51 |
52 | def reset_report(self, filename):
53 | """
54 | 这个方法主要是通过写入文件的方法,先打开cs.YML_REPORT也就是
55 | mkdocs.yml文件,判断文件中是否存在当前写入的内容。
56 | :param filename: 测试用例文件
57 | :return: 测试报告内容
58 | """
59 | try:
60 | result = os.path.exists(cs.REPORT_PATH)
61 | if result == True:
62 | conf.get_config(filename)
63 | reportName = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.REPORT))
64 | report_name = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.R_NAME))
65 | file = open(cs.YML_REPORT, 'r')
66 | list_con = file.readlines()
67 | content = str(list_con).decode("string_escape")
68 | fileContent = "- [%s, %s]"
69 | row = "\n"
70 | _content = fileContent % (reportName + cs.NOW, report_name)
71 | con = row + _content
72 |
73 | if fileContent % (reportName + cs.NOW, report_name) not in content:
74 | f = open(cs.YML_REPORT, 'a+')
75 | f.write(con)
76 | else:
77 | logging.info("内容已经存在 %s" % _content)
78 | except Exception, e:
79 | logging.error("文件路径不存在 %s", e)
80 |
81 | def write_report(self, content):
82 | """
83 | 这个方法用于书写测试报告从而解决之前的通过
84 | logging方式写入导致其他的日志无法实现写入
85 | :param content: 传入文件的内容
86 | :return: None
87 | """
88 | reportName = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.REPORT))
89 | _reportName = reportName + cs.NOW
90 | filename = cs.REPORT_PATH + _reportName
91 | try:
92 | file = open(filename, 'a+')
93 | file.writelines(content)
94 | except Exception, e:
95 | logging.error("文件路径不存在 %s", e)
96 |
97 | def execute_case(self, filename):
98 | """
99 | 执行接口测试用例的方法
100 | :param filename: 用例文件名称
101 | :return: 测试结果
102 | """
103 | conf.get_config(filename)
104 | list = eval(conf.get_title_list())
105 | try:
106 | for i in range(1, len(list)):
107 | title = list[i]
108 | number = conf.get_data(title, key=cs.NUMBER)
109 | name = conf.get_data(title, key=cs.NAME)
110 | method = conf.get_data(title, key=cs.METHOD)
111 | url = conf.get_data(title, key=cs.URL)
112 | data = eval(conf.get_data(title, key=cs.DATA))
113 | _data = request.json.dumps(data,ensure_ascii=False,indent=4)
114 | headers = eval(conf.get_data(title, key=cs.HEADERS))
115 | _headers = request.json.dumps(headers,ensure_ascii=False,indent=4)
116 | testUrl = cs.TEST_URL + url
117 | actualCode = request.api(method, testUrl, _data, headers)
118 | expectCode = conf.get_data(title, key=cs.CODE)
119 |
120 | if actualCode != expectCode:
121 | logging.info("新增一条接口失败报告")
122 | self.write_report(
123 | cs.API_TEST_FAIL % (name, number, method, testUrl, _headers,_data, expectCode, actualCode))
124 | else:
125 | logging.info("新增一条接口成功报告")
126 | self.write_report(cs.API_TEST_SUCCESS % (name, number, method, testUrl, _headers,_data, expectCode, actualCode))
127 | except Exception,e:
128 | logging.error('执行case失败 %s',e)
129 |
130 | def run_test(self, filename):
131 | """
132 | 普通接口测试类方法
133 | :param filename: 接口的用例name
134 | :return: 测试报告
135 | """
136 | reportName = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.REPORT))
137 | _filename = cs.REPORT_PATH + reportName + cs.NOW
138 | try:
139 | if os.path.exists(_filename):
140 | os.remove(_filename)
141 | self.execute_case(filename)
142 | else:
143 | self.execute_case(filename)
144 | except Exception, e:
145 | logging.error("执行接口测试失败 %s", e)
146 |
147 | def write_report_result(self):
148 | """
149 | 这个方法用于书写测试报告结果
150 | :return: None
151 | """
152 | reportName = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.REPORT))
153 | _filename = cs.REPORT_PATH + reportName + cs.NOW
154 | try:
155 | f = file(_filename)
156 | content = f.read()
157 | if content != None:
158 | _count = content.count("Number")
159 | _fail = content.count("Case Fail")
160 | _pass = content.count("Case Pass")
161 | space = content.split('\n')
162 | space.insert(0,cs.RESULT_CONTENT % (_count, _pass, _fail))
163 | _content_ = '\n'.join(space)
164 | fp = file(_filename,'r+')
165 | fp.write(_content_)
166 | except Exception, e:
167 | logging.error("文件路径不存在 %s", e)
168 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 代码编写用例和接口测试
2 |
3 | **公司新来两个妹子一直吐槽,这个接口测试用例用excel维护起来十分费脑费事,而且比较low(内心十分赞同但是不能推翻自己),妹子希望只在编辑器中就能完成所有工作,包括用例编辑、场景设计、数据处理、一键自动化测试、报告生成,于是偷偷的进行了二次改版。**
4 |
5 | 变更内容如下:
6 |
7 | * ###### 1.代码结构
8 |
9 | 
10 |
11 | * ###### 2.新增测试报告网页版和版本管理
12 | * ###### 3.新增用例代码化
13 |
14 |
15 | ##### 一、封装一个获取用例的模块
16 |
17 | 
18 |
19 | > ###### 用例的写法可以按照yml文件的写法,后缀的文件都可为.conf、.config、.ini。[]中的是测试用例场景,下面的参数内容对应接口用例参数。
20 | >
21 | > ###### 简单介绍下python内置模块ConfigParser:
22 | > - ConfigParser 是用来读取配置文件的包。配置文件的格式如下:中括号“[ ]”内包含的为section。section 下面为类似于key:value 的配置内容。(key = value也可以具体方法这次不详细展开,之后写一遍关于ConfigParser的用法,懂原理会让工作更轻松。)
23 | >
24 | > - 这里讲讲为什么配置写在最外层,如果写到文件夹中,怎么都无法读取配置。python执行run命令的时候需要.ini文件跟run 文件在同个文件夹下。所以应该是路径问题导致,之后尝试修复这个BUG。
25 |
26 | (通过操作绝对路径的方法修复此BUG上图已经修复)
27 |
28 |
29 | ###### 这次变更代码实现如下:
30 | ```python
31 | #!/usr/bin/python
32 | # -*- coding: UTF-8 -*-
33 | # 基础包:配置服务
34 |
35 | import ConfigParser
36 |
37 | config = ConfigParser.ConfigParser()
38 |
39 |
40 | def get_config(filename):
41 | """
42 | 获取文件配置
43 | :param filename: 配置文件名
44 | :return: None
45 | """
46 | global config
47 | try:
48 | config.read(filename)
49 | return True
50 | except Exception, e:
51 | print ("读取配置失败 %s" % e)
52 |
53 |
54 | def get_data(title, key):
55 | """
56 | 参数配置
57 | :param title: 配置文件的头信息
58 | :param key: 配置文件的key值
59 | :return: 配置文件的value
60 | """
61 | try:
62 | value = config.get(title, key)
63 | return value
64 | except Exception, e:
65 | print ("获取参数失败 %s" % e)
66 |
67 |
68 | def get_title_list():
69 | """
70 | 获取所有title
71 | :return: title list
72 | """
73 | try:
74 | title = config.sections()
75 | return str(title).decode("string_escape")
76 | except Exception, e:
77 | print ("获取title信息失败 %s", e)
78 | ```
79 |
80 |
81 | #### 二、封装一个日志的模块
82 |
83 | > ###### 这次日志进行了一次更改:会将测试用例返回结果文件内容写入,文件通过mkdocs生成测试报告。
84 | >
85 | > ###### 公司用的微服务,作为testOps所以需要对Docker有一定涉猎,docker.hub官方提供了mkdocs的镜像。拉取官网镜像,将数据卷挂载到搭载测试报告的宿主机上,就可以访问了。你只要维护代码的测试用例,自动更新测试报告。
86 | 看下展示效果:
87 |
88 | 
89 |
90 |
91 | 代码如下:
92 | ```python
93 | #!/usr/bin/python
94 | # -*- coding: UTF-8 -*-
95 | # 基础包:日志服务
96 |
97 | import logging
98 | import constants as cs
99 | import logging.handlers
100 |
101 |
102 | def get_logger(name='report'):
103 | FORMAT = '%(message)s'
104 | filename = cs.REPORT_PATH + name + cs.NOW
105 | logging.basicConfig(level=logging.WARNING, format=FORMAT,
106 | filename=filename, filemode='w')
107 | return logging
108 | ```
109 |
110 |
111 | #### 三、调用接口的requests
112 | 代码如下:
113 | ```python
114 | #!/usr/bin/python
115 | # -*- coding: UTF-8 -*-
116 | # 基础包:接口测试的封装
117 |
118 | import requests
119 | import json
120 |
121 |
122 | def change_type(value):
123 | """
124 | 对dict类型进行中文识别
125 | :param value: 传的数据值
126 | :return: 转码后的值
127 | """
128 | result = eval(json.dumps(value, ensure_ascii=False, encoding="UTF-8"))
129 | return result
130 |
131 |
132 | def api(method, url, data, headers):
133 | """
134 | 定义一个请求接口的方法和需要的参数
135 | :param method: 请求类型
136 | :param url: 请求地址
137 | :param data: 请求参数
138 | :param headers: 请求headers
139 | :return: code码
140 | """
141 | global results
142 | try:
143 | if method == ("post" or "POST"):
144 | results = requests.post(url, data, headers=headers)
145 | if method == ("get" or "GET"):
146 | results = requests.get(url, data, headers=headers)
147 | response = results.json()
148 | code = response.get("code")
149 | return code
150 | except Exception, e:
151 | print ("请求失败 %s" % e)
152 | ```
153 |
154 | #### 四、业务包调用封装包(common.py)
155 | ```python
156 | #!/usr/bin/python
157 | # -*- coding: UTF-8 -*-
158 | # 业务包:通用函数
159 |
160 |
161 | import lib.tezMysql as mysql
162 | import lib.tezLog as log
163 | import lib.tezRequest as request
164 | import lib.tezConfig as conf
165 | import constants as cs
166 | import os
167 |
168 | def prepare_data(host, user, password, db, sql):
169 | """
170 | 数据准备,添加测试数据
171 | :param host: 服务地址
172 | :param user: 用户
173 | :param password: 密码
174 | :param db: 数据库名
175 | :param sql: 执行的SQL
176 | :return:
177 | """
178 | mysql.connect(host, user, password, db)
179 | res = mysql.execute(sql)
180 | mysql.close()
181 | print ("Run sql: the row number affected is %s" % res)
182 | return res
183 |
184 |
185 | def get_prepare_sql(filename, key):
186 | """
187 | 获取预备执行的SQL
188 | :param title: 配置文件头信息
189 | :param key: 配置文件值
190 | :return: Value
191 | """
192 | try:
193 | conf.get_config(filename)
194 | value = conf.get_data(title=cs.TITLE, key=key)
195 | return value
196 | except Exception, e:
197 | print ("获取用例参数值失败 %s" % e)
198 |
199 |
200 | def reset_report(filename):
201 | try:
202 | result = os.path.exists(cs.REPORT_PATH)
203 | if result == True:
204 | conf.get_config(filename)
205 | reportName = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.REPORT))
206 | report_name = eval(conf.get_data(title=cs.REPORT_NAME, key=cs.R_NAME))
207 | file = open(cs.YML_REPORT, 'r')
208 | list_con = file.readlines()
209 | content = str(list_con).decode("string_escape")
210 | fileContent = "- [%s, %s]"
211 | row = "\n"
212 | con = row + fileContent % (reportName + cs.NOW, report_name)
213 |
214 | if fileContent % (reportName + cs.NOW, report_name) not in content:
215 | f = open(cs.YML_REPORT, 'a+')
216 | f.write(con)
217 | else:
218 | print ("内容已经存在 %s" % con)
219 | except Exception, e:
220 | print ("文件路径不存在 %s", e)
221 |
222 |
223 | def run_test(filename):
224 | conf.get_config(filename)
225 | list = eval(conf.get_title_list())
226 | reportName = eval(conf.get_data(cs.REPORT_NAME, key=cs.REPORT))
227 | logging = log.get_logger(reportName)
228 | for i in range(2, len(list)):
229 | title = list[i]
230 | number = eval(conf.get_data(title, key=cs.NUMBER))
231 | name = str(conf.get_data(title, key=cs.NAME))
232 | method = str(conf.get_data(title, key=cs.METHOD))
233 | url = str(conf.get_data(title, key=cs.URL))
234 | data = request.change_type(conf.get_data(title, key=cs.DATA))
235 | headers = eval(conf.get_data(title, key=cs.HEADERS))
236 | testUrl = cs.TEST_URL + url
237 | actualCode = request.api(method, testUrl, data, headers)
238 | expectCode = conf.get_data(title, key=cs.CODE)
239 |
240 |
241 | if actualCode != expectCode:
242 | print "FailInfo"
243 | print number
244 | logging.warning("- FailCase : %s", name)
245 | logging.warning(" - Number : %s", number)
246 | logging.warning(" - Method : %s", method)
247 | logging.warning(" - Url : %s", testUrl)
248 | logging.warning(" - Data : ``` %s ```", data)
249 | logging.warning(" - Headers : ``` %s ```", headers)
250 | logging.warning(" - 期望值 : %s", expectCode)
251 | logging.warning(" - 实际值 : %s", str(actualCode))
252 | logging.warning("*****************")
253 | else:
254 | print number
255 | print "TrueInfo"
256 | logging.warning("- TrueCase %s", name)
257 | logging.warning("*****************")
258 |
259 | ```
260 | #### 五、执行包(run.py)
261 | ```python
262 | import util.common as common
263 | import sys
264 |
265 | # FILENAME = sys.argv[1]
266 |
267 | FILENAME = "proUser.ini"
268 |
269 | """1.新建测试报告目录"""
270 | common.reset_report(filename=FILENAME)
271 |
272 | """2.执行测试用例"""
273 | common.run_test(filename=FILENAME)
274 |
275 | ```
276 | > ###### PS:有个全局变量包constant.py,里面看到是参数目录文件相关的。
277 |
--------------------------------------------------------------------------------